使用反射将 IList 投射<Interface>到列表<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是我从端点和实体返回的内容。Order是我在内部(我使用DI/IOC)用于业务逻辑、数据操作等。由于我的业务层从实体命名空间返回类型,但是端点从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.DalerOrder表示包含数据的实例化对象。

一切都很好,直到我得到类型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);
}

我不确定我想做的事情是否可能。我知道Generics和Reflection不能很好地结合在一起,所以如果有一个解决方案,它可能会对我真正想要实现的目标过于复杂。如果情况越来越糟,我可以在我的每个DTO上放置一个静态方法,该方法将接受源类型作为参数并返回DTO的实例,但我希望尽可能避免手动将字段从实体映射到DTO。

非常感谢您的帮助。

  1. 您可以使用targetProp.GetGenericArguments()[0];获取要将收藏内容映射到的项目类型
  2. 您可以使用Activator.CreateInstance创建List<T>T在运行时而不是编译时已知
  3. 可以使用Activator.CreateInstance创建要映射到的类型的实例
  4. 在调用MapObject时,不能再依赖类型推理了。您还需要通过这里的反射创建适当的泛型方法,并调用它
  5. 你不能简单地在列表中调用Add,因为你不知道它是什么类型的列表。你可以将它强制转换为ICollection,然后在它上调用Add

你就不能使用类似于AutoMapper的东西吗?这些都是人们已经解决的问题,你为什么不利用他们的工作呢?

相关内容

  • 没有找到相关文章

最新更新