2

我正在使用反射从 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>我拥有的泛型,例如,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); 

因为sourceValis aDTOSearchField<T>destinationPropertyis a SearchField<T>,并且它们都具有 T 类型的属性,所以感觉如果您在运行时之前不知道 T 是什么,这并不重要。

我知道演员表不会起作用,因为 T 直到运行时才知道。除了针对每种可能类型的 If-Then-Else 之外,还有什么方法可以实现我想要的吗?如果我必须这样做,它似乎会破坏使用泛型的优势。

谢谢,

4

1 回答 1

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 类,则有一些方法可以解决这个问题,但对于这个答案来说,讨论太多了。

于 2012-12-23T14:09:54.197 回答