Как с помощью NHibernate создать INHibernateProxy? - PullRequest
1 голос
/ 16 июня 2010

После долгих чтений о сериализации я решил попытаться создать 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 обратно в сущность, для сущностей, которые не были инициализированы, я хочу создать прокси, чтобы, если сущность хочет получить к ней доступ, она может,Тем не менее, я не могу понять, как создать прокси.Я использую Касл, если это актуально.

Я перепробовал кучу вещей без удачи.Приведенный ниже код - беспорядок, в основном потому, что я пробовал что-то наугад, не зная, что мне делать.У кого-нибудь есть предложения?

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);
    }
}

1 Ответ

1 голос
/ 17 июня 2010

Это может быть один из тех случаев, когда ответом является «не» или, по крайней мере, «вы, вероятно, не должны».Если вы отображаете DTO непосредственно в сопоставленные объекты NHibernate, вы на самом деле не используете сопоставленные объекты в качестве объектов домена, просто как причудливый способ помещать данные в базу данных и из нее.Это, конечно, может быть все, что вам нужно, но, сделав это самостоятельно в прошлом, я обнаружил, что проблематично пытаться использовать один и тот же формат данных DTO в обоих направлениях.Если вы переходите кросс-процесс, вы превращаете сервис в (сложный в обслуживании) слой CRUD.Если вы находитесь в том же процессе, вы выполняете ненужные перестановки данных с DTO.

Отправка DTO - это хорошо, но рассмотрите возможность проецирования данных в формат, более точно соответствующий потребностям клиента.То, что вы получаете, лучше выражается в конкретных DTO, которые выражают только данные, необходимые для выполнения фактического действия (по существу, объекты Command).С несколькими автоматическими свойствами их тривиально построить.После этого у вас может быть бизнес-метод, который выполняет необходимое действие только с необходимой информацией и в формате, подходящем для выполняемого действия.Мое основное использование AutoMapper (которое качается) в эти дни состоит в том, чтобы преобразовать входящие DTO в типы, которые могут использовать методы домена.

Кроме того, публичные сеттеры на отображаемых объектах нежелательны, поскольку они позволяют манипулировать объектом любымкод без какой-либо проверки.Это означает, что любая их модификация может оставить их в недопустимом состоянии.

Если вы действительно не заботитесь о вышеизложенном (и это не всегда применимо) способе, которым вы загружаете отдельные экземпляры, оставляете вас открытым, то делаете многозагрузка отдельных баз данных, которая является потенциальной проблемой производительности.

...