我正在使用反射从DTO(xSearchQuery)在一个类(xSearchObject)上映射(设置属性)。我试图减少代码,以便更容易看到我想要实现的目标。我无法更改SearchField
,但我可以更改DTOSearchField
。
DTOSearchField<T>
的 n 属性。 SearchField<T>
的 n 属性。 来源类属性类型
public class DTOSearchField<T> : IDTOSearchField
{
public T EqualTo;
}
目标类属性类型:
public class SearchField<T> : ISearchField
{
public void WhereEquals(T value)
{
_clauses.Add(_name + " = " + Converter.ConvertValueToSql(value));
}
// etc
}
映射:(基于Lightweight Object to Object Mapper)
如果不是通用的DTOSearchField<T>
,我可以非常愉快地进行映射,例如,StringDTOSearchField
,IntDTOSearchField
等类并转换为那些。因此对于每个源属性:
if (sourceVal.GetType().IsAssignableFrom(typeof(StringDTOSearchField)))
{
var destinationProperty = destinationPropertyAccessor.GetPropertyValue(destination, propertyMatch.DestinationProperty.Name) as SearchField<string>;
var sourceStringField = sourceVal as StringSearchField;
if (sourceStringField != null)
{
if (!string.IsNullOrEmpty(sourceStringField.EqualTo)) destinationProperty.WhereEquals(sourceStringField.EqualTo);
}
}
else if (sourceVal.GetType().IsAssignableFrom(typeof(IntDTOSearchField)))
{
// Etc
}
或者我可以保留通用DTOSearchField<T>
并根据以下内容加载If-Then-elses:
Type t = sourceVal.GetType().GetGenericArguments()[0];
转换为适当的类型,
但我觉得我应该能做类似的事情:
Type t = sourceVal.GetType().GetGenericArguments()[0];
var destinationProperty = destinationPropertyAccessor.GetPropertyValue(destination, propertyMatch.DestinationProperty.Name) as SearchField<t>;
destinationProperty.WhereEquals(sourceVal.EqualTo.Value);
由于sourceVal
是DTOSearchField<T>
且destinationProperty
是SearchField<T>
,并且它们都具有T类属性,所以如果你不这样做就感觉无所谓知道T到运行时是什么。
我理解演员阵容不会起作用,因为T在运行时才知道。反正是为了实现我想要的,除了If-Then-Else以外的每种可能的类型?如果我必须这样做,它似乎打败了使用泛型的优势。
谢谢,
答案 0 :(得分:0)
您可以通过反射调用WhereEquals方法,但我建议您按照以下方式利用泛型(因为您有权更改DTOSearchField):
public interface IDTOSearchField
{
void MapToSearchField(ISearchField searchField);
}
public class DTOSearchField<T> : IDTOSearchField
{
public T EqualTo;
public void MapToSearchField(ISearchField searchField)
{
if (!(searchField is SearchField<T>))
{
throw new ArgumentException("SearchField must be of type " + typeof(T).FullName + ".", "searchField");
}
((SearchField<T>)searchField).WhereEquals(EqualTo);
}
}
然后,您可以在界面上使用此新方法进行映射,如下所示:
public void MapField(IDTOSearchField source, ISearchField destination)
{
source.MapToSearchField(destination);
}
如果您不想让DTOSearchField类了解SearchField类,可以采取相应方法,但这对于这个答案来说太过分了。