2010-06-16 2 views
1

После долгих чтений о сериализации я решил попробовать создать DTO. После большего чтения я решил использовать AutoMapper.С NHibernate, как я могу создать INHibernateProxy?

То, что я хотел бы сделать, это преобразовать родительский элемент (достаточно просто) и преобразовать свойства объекта, если они были инициализированы, что я сделал с помощью 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

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

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

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

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

+0

Я сам не большой поклонник этого подхода, поэтому я определенно понимаю ответ «не надо». Я хочу сделать это в ограниченном сценарии. Причина, по которой я пытаюсь это сделать, я работаю над классическим сайтом ASP.NET. Продукты, которые я продаю, очень настраиваемые; выбор некоторых параметров, включение других опций, все из которых диктуют ценообразование. Если я заполню свою сущность, я могу вызвать функцию, чтобы оценить ее. Ценообразование поступает в базу данных для получения таблиц динамических цен на основе опций. В настоящее время я перестраиваю сущность на каждом посту/обратном вызове, который является утомительным. Я надеялся на что-то более автоматическое. – Eric

+0

Это делает вещи более проблематичными.Некоторые возможные варианты: - Использовать объекты запроса, которые инкапсулируют поиск цен. Я делаю это с объектами, которые возвращают DetachedCriteria, чтобы мои контроллеры (в MVC) могли добавлять пейджинг, сортировку и т. Д. Вы могли бы создать базовый класс, который затем может быть настроен для каждого обстоятельства. - Предварительно рассчитайте цены. Конечно, вы говорите, что у вас много вариантов, поэтому это может быть очень большой набор данных. Возможно, что-то может работать с NoSQL DB. Я все равно решительно возражаю против расположения DTO 1: 1 и сопоставленного объекта. Он просто просит неприятностей. – AbstractCode

+0

Это система, которую я унаследовал, которая иногда может быть немного архаичной. Ценообразование охватывает около 10 различных таблиц и требует широкого доступа к данным. У нас есть работа с перестройкой объекта на основе viewstate, но он уродлив. – Eric

Смежные вопросы