Создание бизнес-приложений с помощью Silverlight - Преобразование объектов сообщения
ОГЛАВЛЕНИЕ
Преобразование объектов сообщения
Кроме этого, метод GetAgentScriptCallback преобразует объекты выходного сообщения (известные также как DataContracts) из службы в объект клиентской стороны, представляющий обычную семантику клиентской стороны. Например, при проектировании объектов сообщений серверной стороны можно не заботиться о привязке данных, обращая при этом внимание на то, что по своей природе служба используется многократно и должна предусматривать широкий диапазон применений, а не только центр обработки вызовов.
Помимо этого разумно избегать тесной связи с объектами сообщения, поскольку у клиента не будет возможности контролировать изменения объектов сообщений. Методика преобразования объектов сообщения в объекты клиентской стороны не применима напрямую к Silverlight, но в общем случае может быть применена к любому потребителю веб-службы, если требуется избежать тесной связи на этапе проектирования.
Я принял решение сделать реализацию преобразователей объектов крайне простой — никаких экзотических вложенных обобщенных типов, лямбда-выражений или инверсий контейнеров элементов управления. ClientEntityTranslator является абстрактным классом, определяющим метод ToClientEntity(), который каждый подкласс должен переопределять.
public abstract class ClientEntityTranslator
{
public abstract ClientEntities.ClientEntity ToClientEntity(object
serviceOutputEntity);
}
Каждый дочерний класс является уникальным для типа обмена между службами; следовательно, я буду создавать столько преобразователей, сколько потребуется. В моем демонстрационном примере имеется три типа вызовов служб: IUserProfile.GetUser(), ICallService.GetAgentScript() и ICallService.GetOrderDetails(). Поэтому я создал три преобразователя, как показано на рис. 6.
Рис. 6 Преобразователь объекта сообщения в объект клиентской стороны
public class SvcOrderToClientOrder : ClientEntityTranslator
{
//singleton
public static ClientEntityTranslator entityTranslator = new
SvcOrderToClientOrder();
private SvcOrderToClientOrder() { }
public override ClientEntities.ClientEntity ToClientEntity(object
serviceOutputEntity)
{
CallBusinessProxy.OrderInfo oi = serviceOutputEntity as
CallBusinessProxy.OrderInfo;
ClientEntities.Order bindableOrder = new ClientEntities.Order();
bindableOrder.OrderNumber = oi.Order.OrderNumber;
//code removed for brevity ...
return bindableOrder;
}
}
public class SvcUserToClientUser : ClientEntityTranslator
{
//code removed for brevity ...
}
public class SvcScriptToClientScript : ClientEntityTranslator
{
//code removed for brevity ...
}
}
Если вы обратили внимание, вышеприведенные преобразователи имеют неизменное состояние и используют единственный шаблон. Из соображений согласованности преобразователь должен быть в состоянии наследовать классу ClientEntityTranslator и он должен быть singleton-классом во избежание попадания сборщику мусора.
Я постоянно использую один и тот же экземпляр при любом вызове соответствующей службы. Можно было бы также создать ServiOutputEntityTranslator для взаимодействия служб, которое требует больших входных сообщений (обычно так бывает в случае вызова транзакционной службы), с помощью следующего определения класса.
public abstract class ServiOutputEntityTranslator
{
public abstract object ToServiceOutputEntity(ClientEntity
clientEntity);
}
Если вы обратите внимание на значение, возвращаемое упомянутой выше функцией, то увидите, что это «object», поскольку я не управляю базовым классом объектов сообщения (это было бы возможно в данном демонстрационном примере, но не в реальной ситуации). Безопасность типа будет реализована соответствующими преобразователями. Для упрощения демонстрационного примера я не сохраняю никакие данные на сервере, поэтому в данный пример не входят никакие преобразователи объектов клиента в объекты сообщения.