Я пытаюсь указать известный тип в своей конфигурации, но у меня есть проблемы с тем, что она происходит из Объекта. Я могу заставить его работать, указав известный тип через атрибут. Но в этом случае я должен заставить его работать от конфигурации.
Вот пример. Следующее хорошо работает:
[ServiceContract]
[ServiceKnownType(typeof(MyData))]
public interface IContract
{
[OperationContract]
void Send(object data);
}
[DataContract]
public class MyData
{
[DataMember]
public string Message { get; set; }
}
Но если я удаляю атрибут ServiceKnownType и помещаю следующее в конфигурацию:
<system.runtime.serialization>
<dataContractSerializer>
<declaredTypes>
<add type="System.Object, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<knownType type="WpfApplication1.MyData, WpfApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</add>
</declaredTypes>
</dataContractSerializer>
</system.runtime.serialization>
Я добираюсь, ConfigurationErrorsException с сообщением "Значение для свойства 'тип' не допустим. Ошибка: система типов. Объект не может использоваться в качестве заявленного типа в конфигурации".
Там должен так или иначе сделать эту работу через конфигурацию?
Ответ оказался в том, что невозможно сделать то, что я хочу, только в конфигурационном файле. Конфиг выше соответствует атрибуту [KnownType], используемому в DataContracts. Похоже, нет способа реализовать [ServiceKnownType] в конфигурации.
Альтернативный подход заключается в использовании атрибута [ServiceKnownType(methodName, type)] с пользовательским разделом конфигурации. Новый конфиг выглядит так:
<configuration>
<configSections>
<section
name="serviceKnownTypes"
type="WpfApplication1.ServiceKnownTypesSection, WpfApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</configSections>
<serviceKnownTypes>
<declaredServices>
<serviceContract type="WpfApplication1.IContract, WpfApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
<knownTypes>
<knownType type="WpfApplication1.MyData, WpfApplication1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</knownTypes>
</serviceContract>
</declaredServices>
</serviceKnownTypes>
</configuration>
Контракты:
[ServiceContract]
[ServiceKnownType("GetServiceKnownTypes", typeof(KnownTypeHelper))]
public interface IContract
{
[OperationContract]
void Send(object data);
}
[DataContract]
public class MyData
{
[DataMember]
public string Message { get; set; }
}
Класс-помощник, содержащий обратный вызов, возвращающий список известных типов
public static class KnownTypeHelper
{
public static IEnumerable<Type> GetServiceKnownTypes(ICustomAttributeProvider provider)
{
List<Type> result = new List<Type>();
ServiceKnownTypesSection serviceKnownTypes = (ServiceKnownTypesSection)ConfigurationManager.GetSection("serviceKnownTypes");
DeclaredServiceElement service = serviceKnownTypes.Services[((Type)(provider)).AssemblyQualifiedName];
foreach (ServiceKnownTypeElement knownType in service.KnownTypes)
{
result.Add(knownType.Type);
}
return result;
}
}
Информацию о создании пользовательских секций конфига можно найти здесь:
http://msdn.microsoft.com/en-us/library/2tw134k3.aspx
http://msdn.microsoft.com/en-us/library/system.configuration.configurationcollectionattribute.aspx