簡體   English   中英

使用反射來投射IList <Interface> 列出 <T>

[英]Using reflection to cast an IList<Interface> to List<T>

我正在使用WCF服務,但遇到了將實體映射到DTO的麻煩。 考慮以下

 namespace Foo.Entities
 {
      public class Order : IOrder
      {
          public string Name { get;set; }
          public string Address { get;set; }
          public IList<ILocation> Locations { get;set; }
      }
 }

 namespace Foo.DTO
 {
      [DataContract]
      public class Order 
      {
          [DataMember]
          public string Name { get;set; }
          [DataMember]
          public string Address { get;set; }
          [DataMember]
          public List<Location> Locations { get;set; }
      }
 }

這一切都非常簡單:DTO.Order是我從端點和Entities返回的內容。Order是我內部在使用(我使用DI / IOC)進行業務邏輯,數據操作等的內容。由於我的業務層返回了類型從Entities命名空間返回,但是端點從DTO命名空間返回類型,我寫了一個小的映射方法,它將采用一種類型並將其映射到另一種類型,如下所示:

 public TTarget MapObject<TSource, TTarget>(TSource source, TTarget target)
            where TSource : class
            where TTarget : class
        {
            foreach (var prop in source.GetType().GetProperties())
            {
                var targetProp = target.GetType().GetProperty(prop.Name, BindingFlags.Public | BindingFlags.Instance);
                if(targetProp == null || !targetProp.CanWrite) continue;

                if (prop.PropertyType.GetGenericTypeDefinition() == typeof (IList<>))
                {
                    ??
                }
                else{ targetProp.SetValue(target, prop.GetValue(source)); }
            }

            return target;
        }

然后,我像這樣調用此方法:

factory.MapObject(Entities.DealerOrder, new GTO.DealerOrder())

其中Entities.DealerOrder表示包含數據的實例化對象。

一切工作正常,直到獲得IList類型的屬性,而且我對如何將IList轉換為List感到困惑。 我知道需要做什么,但是到目前為止,我閱讀的所有文檔都沒有為我指明正確的方向。

偽是

if (prop.PropertyType.GetGenericTypeDefinition() == typeof (IList<>))
{
    var lst = new List<type of targetProp>()
    foreach(var val in prop.GetValue())
    {
        var item = new Location() (I have to figure out this initialization based on the List type of targetProp.  In this case it would be List<Location>)
         var retval = MapObject(val, item);
         lst.Add(retval);
    }
    targetProp.SetValue(target, lst);
}

我不確定我想做什么甚至可能。 我知道,泛型和反射不能很好地結合在一起,因此,如果有解決方案,那么對於我真正想要實現的目標而言可能過於復雜。 如果情況變得更糟,我可以在每個DTO上放置一個靜態方法,該方法將接受源類型作為參數並返回DTO的實例,但是我想避免必須手動將字段從Entity映射到DTO如果可能的話。

任何幫助是極大的贊賞。

  1. 您可以使用targetProp.GetGenericArguments()[0]; 獲取您想要將收藏內容映射到的項目類型。
  2. 您可以使用Activator.CreateInstance來創建List<T>其中在運行時而不是編譯時就知道T
  3. 您可以使用Activator.CreateInstance創建要映射到的類型的實例。
  4. 調用MapObject時,您不能再依賴類型推斷了。 您也需要通過反射來創建適當的泛型方法,然后調用它。
  5. 您不能簡單地在列表上調用“ Add ”,因為您不知道列表是哪種類型。 您可以將其ICollectionICollection然后調用Add

您不能只使用AutoMapper之類的東西嗎? 這些是人們已經解決的問題,您為什么不使用他們的工作呢?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM