Автор: Sergey Teplyakov

Применение атрибута ServiceKnownTypeAttribute

Определение класса ServiceKnownTypeAttribute следующее:
[AttributeUsageAttribute(AttributeTargets.Class|AttributeTargets.Method|AttributeTargets.Interface, Inherited = true, AllowMultiple = true)]public sealed class ServiceKnownTypeAttribute : Attribute{ public ServiceKnownTypeAttribute(Type type), public ServiceKnownTypeAttribute(string methodName), public ServiceKnownTypeAttribute(string methodName, Type declaringType), //Остальные члены}
Атрибут ServiceKnownTypeAttribute применяется для конкретной операции или контракту целиком.
[ServiceContract(SessionMode = SessionMode.Required)]public interface IService{ [OperationContract] [ServiceKnownType(typeof(Circle))] [ServiceKnownType(typeof(Square))] Shape CreateShape(ShapeType shapeType, int id), //Такого поведения нельзя добиться с применением атрибута KnownTypeAttribute [OperationContract] [ServiceKnownType(typeof(Shape))] [ServiceKnownType(typeof(Circle))] [ServiceKnownType(typeof(Square))] void ProcessShape(object shape),} [ServiceContract(SessionMode = SessionMode.Required)][ServiceKnownType(typeof(Circle))][ServiceKnownType(typeof(Square))]public interface IService{ [OperationContract] Shape CreateShape(ShapeType shapeType, int id),}
У этого способа есть несколько особенностей. Во-первых, хотя можно применить атрибут ServiceKnownType к отдельному методу, на самом деле эффект будет такой же, как и от применения этого атрибута к контракту целиком, т.е. будет затронут не только этот метода, а все методы контракта, в которых участвует соответствующий базовый класс. Во-вторых, если не будет применяться совместное использование типов между клиентом и сервером, то приведенные примеры приведут к генерации класса Shape с атрибутами KnownTypeAttribute, а не к применению атрибута ServiceKnownTypeAttribute к сгенерированному контракту. Остальные версии конструктор ServiceKnownTypeAttribute используются для указания метода, возвращающего перечень известных типов. Один из конструкторов принимает строковый параметр и тип.
[ServiceContract][ServiceKnownType('GetKnownTypes', typeof(Helper))]public interface IService { [OperationContract] Shape CreateShape(ShapeType shapeType, int id),}static class Helper { static IEnumerable<,Type>, GetKnownTypes(ICustomAttributeProvider provider) { return new Type[] { typeof(Circle), typeof(Square) }, }}
Другой конструктор принимает только строку с именем метода и может применяться напрямую к классу службы (а не интерфейсу службы).
[ServiceContract][ServiceKnownType('GetKnownTypes')]public class Service { static IEnumerable<,Type>, GetKnownTypes(ICustomAttributeProvider provider) { return new Type[] { typeof(Circle), typeof(Square) }, } [OperationContract] public Shape CreateShape(ShapeType shapeType, int id) { ... }}
ПРИМЕЧАНИЕ
В отличие от атрибута KnownTypeAttribute метод, имя которого передается атрибуту ServiceKnownType, должен содержать параметр ICustomAttributeProvider. Кроме того, при попытке использовать метод с неверной сигнатурой вы получите исключение при попытке открытия службы, а не во время обновления метаданных службы клиентом

Использование конфигурационного файла приложения

Задание перечня известных типов с помощью атрибутов подразумевает, что вы заранее знаете, какие типы будут передаваться между клиентом и службой. В противном случае, понадобиться постоянная перекомпиляция, развертывание и обновление метаданных, для поддержания перечня известных типов в актуальном состоянии. Альтернативой может служить декларативное объявление известных типов в конфигурационном файле приложения сервиса. Для этого необходимо добавить информацию об известных типах в конфигурационный файл приложения или web.config:
<,system.runtime.serialization>, <,dataContractSerializer>, <,declaredTypes>, <,add type = 'Server.Shape, Server'>, <,knownType type = 'Server.Circle, Server'/>, <,knownType type = 'Server.Square, Server'/>, <,/add>, <,/declaredTypes>, <,/dataContractSerializer>, <,/system.runtime.serialization>,
ПРИМЕЧАНИЕ
Для сборок со строгим именем (strongly named assemblies) строка, содержащая описание типа, помимо полного имени типа и названия сборки должна содержать номер версии, идентификатор регионального стандарта и маркер открытого ключа. Пример использования класса EventArgs из сборки mscorlib будет следующим: add type='System.EventArgs, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'
В случае применения конфигурационного файла на стороне сервиса, известные типы будут добавляться в экспортируемые метаданные службы, и будут влиять на генерацию кода на стороне клиента. При совместном использовании типов между сервисом и клиентом в сгенерированном коде будет добавлен атрибут ServiceKnownTypeAttribute для всех методов, аргументы которых добавлены в перечень известных типов в конфигурационном файле сервиса.
[GeneratedCodeAttribute('System.ServiceModel', '3.0.0.0')][ServiceContractAttribute(ConfigurationName='ServiceReference.IService')]public interface IService { [OperationContractAttribute(Action='http://tempuri.org/IService/CreateShape', ReplyAction='http://tempuri.org/IService/CreateShapeResponse')] [ServiceKnownTypeAttribute(typeof(Server.Circle))] [ServiceKnownTypeAttribute(typeof(Server.Square))] Server.Shape CreateShape(Server.ShapeType shapeType, int id),}
При отсутствия совместного использования типов, будет использован атрибут KnownTypeAttribute для базового класса иерархии:
[DebuggerStepThroughAttribute()][GeneratedCodeAttribute('System.Runtime.Serialization', '3.0.0.0')][DataContractAttribute(Name='Shape', Namespace='http://schemas.datacontract.org/2004/07/Server')][SerializableAttribute()][KnownTypeAttribute(typeof(Client.ServiceReference.Circle))][KnownTypeAttribute(typeof(Client.ServiceReference.Square))]public partial class Shape : object, IExtensibleDataObject, INotifyPropertyChanged { }
Известные типы могут добавляться не только в конфигурационный файл сервиса, но и в конфигурационный файл клиентского приложения, но в этом случае предполагается совместное использование типом между клиентом и сервисом.

Комментариев нет:

Отправить комментарий

Следующее Предыдущее Главная страница
Помогла статья? Оцените её!
0 из 5. Общее количество голосов - 0
 

You have no rights to post comments

Дмитрий Крикунов

Публикую статьи, обучающие курсы и новости по программированию: алгоритмам, языкам (С++, Java), параллельному программированию, паттернам и библиотекам (Qt, boost).