1

在大量阅读有关序列化的信息后,我决定尝试创建 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);
    }
}
4

1 回答 1

1

这可能是答案为“不”或至少“您可能不应该”的情况之一。如果您将 DTO 直接映射到 NHibernate 映射对象中,那么您并没有真正将映射对象用作域对象,而只是将数据推入和推出数据库的一种奇特方式。这当然可能是您所追求的,但过去我自己做过这件事,我发现尝试在两个方向上使用相同的 DTO 数据格式是有问题的。如果你要跨进程,你已经把服务变成了一个(难以维护的)CRUD 层。如果您在同一进程中,则您正在使用 DTO 进行不必要的数据混洗。

发送 DTO 很好,但考虑将数据投影成更接近客户实际需要的格式。你得到的东西最好用特定的 DTO 来表达,这些 DTO 只表达执行实际操作所需的数据(本质上是 Command 对象)。通过一些自动属性,它们构建起来很简单。然后,您可以拥有一个业务方法,该方法仅使用必要的信息执行必要的操作,并且采用适合正在执行的操作的格式。这些天我主要使用 AutoMapper(它确实很棒)是将传入的 DTO 转换为域方法可以使用的类型。

此外,映射对象上的公共设置器是不可取的,因为它们允许对象被任何代码操作而无需任何验证。这意味着对它们的任何修改都可能使它们处于无效状态。

如果您并不真正关心上述内容(并且它并不总是适用),那么您加载单个实例的方式确实会让您打开做许多单独的数据库加载,这是一个潜在的性能问题。

于 2010-06-17T10:27:00.893 回答