将具有reflection / Cast属性的泛型属性映射到泛型类型

时间:2012-10-02 10:31:27

标签: c# generics mapping

我正在使用反射从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>,我可以非常愉快地进行映射,例如,StringDTOSearchFieldIntDTOSearchField等类并转换为那些。因此对于每个源属性:

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以外的每种可能的类型?如果我必须这样做,它似乎打败了使用泛型的优势。

谢谢,

1 个答案:

答案 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类,可以采取相应方法,但这对于这个答案来说太过分了。