2011-11-22 42 views
0


我已經爲IQueryable類創建了一個擴展方法,以將通用源類的列表轉換爲其他通用目標類(.net3)的列表。 5)
我使用反射從源對象值獲取屬性並將其分配給destinvation對象。

的類的源代碼如下:使用其他類的屬性值創建類對象列表的擴展方法

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Linq.Expressions; 
using System.Reflection; 
using System.Text.RegularExpressions; 

namespace System.Linq 
{ 
    public static class QueryableExtensions 
    { 
     public static IQueryable<TDest> ToDTO<TDest>(this IQueryable<TSource> source)//getting error on this line 
     { 
      return DTOTranslator<TDest>.ConvertToDTO<TDest>(source); 
     } 
    } 

    public class DTOTranslator<TSource> 
    { 
     public static IQueryable<TDest> ConvertToDTO<TDest>(IQueryable<TSource> source) 
     { 
      List<TDest> destinationList = new List<TDest>(); 
      List<TSource> sourceList = source.ToList<TSource>(); 

      var sourceType = typeof(TSource); 
      var destType = typeof(TDest); 
      foreach (TSource sourceElement in sourceList) 
      { 
       TDest destElement = Activator.CreateInstance<TDest>(); 
       //Get all properties from the object 
       PropertyInfo[] sourceProperties = typeof(TSource).GetProperties(); 
       foreach (PropertyInfo sourceProperty in sourceProperties) 
       { 
        //and assign value to each propery according to property name. 
        PropertyInfo destProperty = destType.GetProperty(sourceProperty.Name); 
        destProperty.SetValue(destElement, sourceProperty.GetValue(sourceElement, null), null); 
        destinationList.Add(destElement); 
       } 
      } 

      return destinationList.AsQueryable(); 
     } 
    } 
} 



然而在我第12行得到的錯誤編譯時 :

The type or namespace name 'TSource' could not be found (are you missing a using directive or an assembly reference?) 



更新:
感謝所有fo r回覆。
現在我已經更新了我的類,如下所示:

public static class QueryableExtensions 
{ 
    public static IQueryable<TDest> ToDTO<TSource, TDest>(this IQueryable<TSource> source) 
    { 
     List<TDest> destinationList = new List<TDest>(); 
     List<TSource> sourceList = source.ToList<TSource>(); 

     var sourceType = typeof(TSource); 
     var destType = typeof(TDest); 
     foreach (TSource sourceElement in sourceList) 
     { 
      TDest destElement = Activator.CreateInstance<TDest>(); 
      //Get all properties from the object 
      PropertyInfo[] sourceProperties = typeof(TSource).GetProperties(); 
      foreach (PropertyInfo sourceProperty in sourceProperties) 
      { 
       //and assign value to each propery according to property name. 
       PropertyInfo destProperty = destType.GetProperty(sourceProperty.Name); 
       destProperty.SetValue(destElement, sourceProperty.GetValue(sourceElement, null), null); 
       destinationList.Add(destElement); 
      } 
     } 

     return destinationList.AsQueryable(); 
    } 
} 


這工作得很好,
現在我不知道的唯一的事情就是覺得─
是否有可能跳過<TSource> paramerter,
如何從IQueryable的元素類型讀取它並定義它的對象? 我的意思是目前我所說的方法

IQueryable<CATEGORY_DTO> dtos = (from p in new MyEntities().CATEGORY select p).ToDTO<CATEGORY, CATEGORY_DTO>(); 

我想稱其爲

IQueryable<CATEGORY_DTO> dtos = (from p in new MyEntities().CATEGORY select p).ToDTO<CATEGORY_DTO>(); 


感謝,NJ

回答

3

試試這個:

public static class QueryableExtensions 
{ 
    public static IQueryable<TDest> ToDTO<TDest, TSource>(this IQueryable<TSource> source) 
    { 
     return DTOTranslator<TSource>.ConvertToDTO<TDest>(source); 
    } 
} 

加入之處在於ToDTO方法還引用了TSource泛型類型(否則你怎麼能引用作爲一個參數 - 這導致了原來的錯誤),這泛型類型是在構造函數給出DTOTranslator (因爲在構造函數中使用TDest是錯誤的,因爲構造函數本身需要的泛型類型的定義是TSource,這是與TDest不同的類型)。

1

需要聲明兩種類型參數:

public static IQueryable<TDest> ToDTO<TSource, TDest>(this IQueryable<TSource> source) 
+0

感謝您的回覆,但是有可能獲得IQueryable列表中的對象類型因爲我只想傳遞目標類型參數? –

+0

這不會編譯,因爲'DTOTranslator'構造函數需要一個不同的泛型類型('TSource'),然後使用'ConvertToDTO'方法的簽名。 –

+0

@NitinJS:您可以將TDest參數放在類而不是方法上,然後編譯器可以使用類型推斷來獲取TSource的類型而無需指定它。 –

1

你應該改變你的函數簽名,並在你的轉換器中稍作改動,我假設你不能傳遞源類型,否則你可以添加通用參數作爲你的函數的輸入。

public static IQueryable<TDest> ToDTO<TDest>(this IQueryable source) 
{ 
    return DTOTranslator<TDest>.ConvertToDTO<TDest>(source); 
} 

public static IQueryable<TDest> ConvertToDTO<TDest>(IQueryable source) 
{ 
    Type sourceType = null; 
    .... 
    foreach(var item in source) 
    { 
     // find source type is it not found till now 
     if (sourceType == null) 
     sourceType = item.GetType(); 
     .... 
    } 
} 
1

yaakov的回答對你的問題是正確的,並且我已經提出了相應的upvoted。不過,我認爲還有更好的答案。

作爲您自己編寫自己的映射反射代碼的替代方法,請考慮使用automapper。

http://automapper.org/

這是已經得到解決,並經過嚴格測試,並通過很多人的使用問題,它有很多的功能和靈活性,並處理了大量的邊緣情況下,你可能不考慮。我建議你檢查一下。

也想補充一點,你使用system.linq命名空間有點奇怪。系統應該保留在框架類庫中的東西,我會建議你使用你自己的命名空間。這並不重要,但是我認爲這會讓你和其他用戶使用類似的東西感到困惑。

相關問題