经过大量关于序列化的阅读后,我决定尝试创建DTO。经过更多阅读,我决定使用AutoMapper。
我想要做的是转换父(很容易)并转换实体属性(如果它们已经初始化),我已经使用ValueResolvers完成,如下所示(我可能会尝试使它成为通用的一旦我得到它完全工作)。这部分有效。
public class OrderItemResolver : ValueResolver<Order, OrderItem>
{
protected override OrderItem ResolveCore(Order source)
{
// could also use NHibernateUtil.IsInitialized(source.OrderItem)
if (source.OrderItem is NHibernate.Proxy.INHibernateProxy)
return null;
else
return source.OrderItem;
}
}
}
当我将DTO转换回实体时,对于未初始化的实体,我想创建一个代理,这样如果实体想要访问它,它就可以。但是,我无法弄清楚如何创建代理。如果那是相关的,我正在使用Castle。
我尝试过一堆没有运气的东西。下面的代码是一团糟,主要是因为我一直在尝试随意而不知道我应该做什么。有人有什么建议吗?
public class OrderItemDTOResolver : ValueResolver<OrderDTO, OrderItem>
{
protected override OrderItem ResolveCore(OrderDTO source)
{
if (source.OrderItem == null)
{
//OrderItem OrderItem = new ProxyGenerator().CreateClassProxy<OrderItem>(); // Castle.Core.Interceptor.
//OrderItem OrderItem = new ProxyGenerator().CreateClassProxy<OrderItem>();
//OrderItem.Id = source.OrderItemId;
//OrderItem OrderItem = new OrderItem();
//var proxy = new OrderItem() as INHibernateProxy;
//var proxy = OrderItem as INHibernateProxy;
//return (OrderItem)proxy.HibernateLazyInitializer
//ILazyInitializer proxy = new LazyInitializer("OrderItem", OrderItem, source.OrderItemId, null, null, null, null);
//return (OrderItem)proxy;
//return (OrderItem)proxy.HibernateLazyInitializer.GetImplementation();
//return OrderItem;
IProxyTargetAccessor proxy = new Castle.Core.Interceptor.
var initializer = new LazyInitializer("OrderItem", typeof(OrderItem), source.OrderItemId, null, null, null, null);
//var proxyFactory = new SerializableProxyFactory{Interfaces = Interfaces, TargetSource = initializer, ProxyTargetType = IsClassProxy};
//proxyFactory.AddAdvice(initializer);
//object proxyInstance = proxyFactory.GetProxy();
//return (INHibernateProxy) proxyInstance;
return null;
//OrderItem.Id = source.OrderItemId;
//return OrderItem;
}
else
return OrderItemDTO.Unmap(source.OrderItem);
}
}
谢谢, 埃里克
也许我过于复杂了。这似乎有效。有人看到任何问题吗?
public class OrderItemDTOResolver : ValueResolver<OrderDTO, OrderItem>
{
protected override OrderItem ResolveCore(OrderDTO source)
{
if (source.OrderItem == null)
return NHibernateSessionManager.Instance.Session.GetISession().Load<OrderItem>(source.AgencyId);
else
return OrderItemDTO.Unmap(source.OrderItem);
}
}
答案 0 :(得分:1)
这可能是答案是“不”,或者至少“你可能不应该”的情况之一。如果您直接将DTO映射到NHibernate映射对象,那么您实际上并不是将映射对象用作域对象,而是将数据推入和导出数据库的奇特方式。这当然可能是你所追求的,但过去我自己做过这一点,我发现试图在两个方向上使用相同的DTO数据格式是有问题的。如果您要进行跨进程,则会将服务转换为(难以维护的)CRUD层。如果你在同一个过程中,你正在使用DTO进行不必要的数据改造。
发送DTO很好,但考虑将数据投影到与客户实际需要的更紧密对齐的格式。在特定的DTO中更好地表达您所获得的内容,这些DTO仅表示执行实际操作所需的数据(本质上是Command对象)。有了一些自动属性,它们很容易构建。然后,您可以拥有一个业务方法,该方法仅使用必要的信息执行必要的操作,并且采用适合于正在执行的操作的格式。我最近主要使用AutoMapper(它确实摇滚)是将传入的DTO转换为域方法可以使用的类型。
此外,映射对象上的公共setter是不合需要的,因为它们允许任何代码操纵对象而无需任何验证。这意味着对它们的任何修改都可能使它们处于无效状态。
如果你真的不关心上面的内容(它并不总是适用)你加载单个实例的方式会让你打开做多个单独的数据库加载,这是一个潜在的性能问题。