我正在使用反射从 DTO (xSearchQuery) 映射(设置属性)到一个类 (xSearchObject)。我试图减少代码,以便更容易看到我想要实现的目标。我无法更改 SearchField
, 但我可以改变 DTOSearchField
.
- 源类有 n 个
DTOSearchField<T>
类型的属性. - 目标类有 n 个
SearchField<T>
类型的属性. - Source 和 Destination 具有相同数量的属性 同名。
源类属性类型
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 之外,还有什么可以实现我想要的吗?如果我必须这样做,它似乎会破坏使用泛型的优势。
谢谢,
最佳答案
您可以通过反射调用 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 类,有多种方法可以解决这个问题,但对于这个答案来说讨论太多了。
关于c# - 将具有反射/Cast 属性的泛型属性映射到泛型类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12688684/