使用反射将IList <interface>强制转换为List <t>

时间:2015-11-18 01:57:02

标签: c# .net wcf reflection

我正在研究一个WCF服务,我遇到了一些障碍,将我的实体映射到我的DTO。请考虑以下

var browseFile = document.getElementById('browseFile');
browseFile.ondragover = function () {
    return false;
};
browseFile.ondrop = function (event) {
    event.preventDefault && event.preventDefault();
    var files = event.dataTransfer.files;
    console.log(files);
    return false;
};

这一切都非常简单:DTO.Order是我从我的端点和Entities.Order返回的内容是我在内部使用(我使用DI / IOC)用于业务逻辑,数据操作等。从我的业务layer从Ent​​ities命名空间返回类型,但是端点从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; }
      }
 }

然后我这样调用这个方法:

 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;
        }

其中Entities.DealerOrder表示包含数据的实例化对象。

一切正常,直到我到达IList类型的属性,我对如何将IList转换为List感到茫然。我知道需要发生什么,但到目前为止我读到的所有文档都没有指出我正确的方向。

伪是

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

我不确定我想做什么是可能的。我知道泛型和反射不能很好地混合,所以如果有一个解决方案,它可能对我真正想要完成的事情过于复杂。如果情况变得更糟,我可以在我的每个DTO上放置一个静态方法,它将接受源类型作为参数并返回DTO的实例,但我想避免必须手动将实体中的字段映射到DTO如果可能的话。

非常感谢任何帮助。

1 个答案:

答案 0 :(得分:2)

  1. 您可以使用targetProp.GetGenericArguments()[0];来获取要将收藏内容映射到的项目类型。
  2. 您可以使用Activator.CreateInstance创建List<T>T在运行时已知道Activator.CreateInstance,而不是在编译时。
  3. 您可以使用MapObject创建要映射到的类型的实例。
  4. 再次呼叫Add时,您无法依赖类型推断。你也需要在这里通过反射创建适当的泛型方法,然后调用它。
  5. 您无法在列表中拨打ICollection,因为您不知道它是什么类型的列表。您可以将其转换为Add并在其上调用Group A - Item 1 - Item 2 - Item 3 Group B - Item 4 - Item 5 - Item 6 - Item 7
  6. 你不能使用像AutoMapper这样的东西吗?那些是人们已经解决的问题,为什么你不使用他们的工作?