2012-10-02 242 views
2

我正在使用反射來從DTO(xSearchQuery)映射(設置屬性)到一個類(xSearchObject)。我試圖減少代碼,以便更容易地看到我想要實現的目標。我無法更改SearchField,但我可以更改DTOSearchField將泛型屬性與反射/ Cast屬性映射到泛型

  • 源類具有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 
} 

映射:(基於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-別人的的負載基於:

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以外的每一種可能的類型嗎?如果必須這樣做的話,它似乎擊敗了使用泛型的優勢。

感謝,

回答

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類的知識,那麼有辦法解決這個問題,但對於這個答案來說,這太多了。