繁体   English   中英

将具有反射/强制转换属性的通用属性映射到通用类型

[英]Mapping generic properties with reflection / Cast property to a generic type

我正在使用反射将DTO(xSearchQuery)的一个类(xSearchObject)映射(设置属性)。 我已尝试减少代码量,以便更轻松地查看要实现的目标。 我无法更改SearchField ,但可以更改DTOSearchField

  • 源类具有n类型DTOSearchField<T>属性。
  • 目标类具有n个类型为SearchField<T>属性。
  • 源和目标具有相同名称的相同数量的属性。

源类属性类型

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
}

映射:(基于轻量级对象到对象映射器 )如果我有一个通用的DTOSearchField<T>而不是例如StringDTOSearchFieldIntDTOSearchField等类并将其StringDTOSearchField IntDTOSearchFieldStringDTOSearchField ,则我可以非常愉快地进行映射。 因此,对于每个源属性:

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); 

由于sourceValDTOSearchField<T>destinationPropertySearchField<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类有所了解,可以采用一些解决方法,但这对于此答案来说是太多讨论了。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM