我正在开发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。
非常感谢您的帮助。
- 您可以使用
targetProp.GetGenericArguments()[0];
获取要将收藏内容映射到的项目类型 - 您可以使用
Activator.CreateInstance
创建List<T>
,T
在运行时而不是编译时已知 - 可以使用
Activator.CreateInstance
创建要映射到的类型的实例 - 在调用
MapObject
时,不能再依赖类型推理了。您还需要通过这里的反射创建适当的泛型方法,并调用它 - 你不能简单地在列表中调用
Add
,因为你不知道它是什么类型的列表。你可以将它强制转换为ICollection
,然后在它上调用Add
你就不能使用类似于AutoMapper的东西吗?这些都是人们已经解决的问题,你为什么不利用他们的工作呢?