繁体   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