У меня есть следующий интерфейс WCF, который предоставляется через net.tcp:
[ServiceContract]
public interface IMyWCFService
{
[OperationContract]
Response ProcessRequest(Request request);
}
Это обусловлено следующими классами (значительно упрощенными для целей этого вопроса):
[Serializable]
public abstract class Message
{
[XmlAttribute]
public string Sender { get; set; }
[XmlAttribute]
public string Recevier { get; set; }
}
[Serializable]
public abstract class Response : Message
{
[XmlAttribute]
public int EventCode { get; set; }
}
[Serializable]
public abstract class Request : Message
{
[XmlAttribute]
public string SourceSystem { get; set; }
}
[XmlRoot(Namespace="http://blah.blah.com/blah/")]
public class StringRequest : Request
{
[XmlElement]
public string Payload { get; set; }
}
[XmlRoot(Namespace="http://blah.blah.com/blah/")]
public class StringResponse : Response
{
[XmlElement]
public string Payload { get; set; }
}
Примечание. Мы используем XMLSerializer
вместо DataContractSerializer
, поскольку эти классы должны быть совместимы с устаревшими системами на основе .NET 2.
Поскольку интерфейс использует абстрактные классы Запрос / Ответ в методе ProcessRequest, мы должны объявить StringResponse / StringRequest как ServiceKnownType
, например:
[ServiceContract]
[ServiceKnownType(typeof(StringRequest))]
[ServiceKnownType(typeof(StringResponse))]
public interface IMyWCFService
{
[OperationContract]
ResponseMessage ProcessRequest(RequestMessage request);
}
Это прекрасно работает, и все хорошо в мире, однако .....
Слушатель WCF - это всего лишь один из компонентов гораздо большего фреймворка, и классы, описанные выше, используются повсеместно. Мы также разработали структуру, позволяющую нам с относительной легкостью добавлять новые типы сообщений запросов / ответов. Например, я мог бы добавить:
public class CustomRequest : Request
{
public MyCustomXmlSerialisableRequestObject Payload { get; set; }
}
public class CustomResponse: Response
{
public MyCustomXmlSerialisableResponseObject Payload { get; set; }
}
Что также хорошо работает, пока я не получу интерфейс службы WCF. Когда мы добавляем новую пользовательскую пару запрос / ответ, нам также необходимо обновить ServiceKnownType в интерфейсе, чтобы включить их. Что означает, что я должен повторно развернуть службу. Таким образом, вопрос - есть ли способ избежать обновления интерфейса?
В качестве примера, когда мы использовали удаленное взаимодействие, мы могли проходить через любые понравившиеся объекты, если бы они были сериализуемыми, поэтому я предполагаю / надеюсь, что в WCF есть подобное решение.
РЕДАКТИРОВАТЬ: Обновление
Следуя инструкциям, найденным здесь:
http://ashgeek.blogspot.com/2011/02/wcf-serialization-dynamically-add.html
Кажется, я на правильном пути. Однако когда я обновляю ссылку на службу клиента, она включает все динамические типы в ссылку на службу. Это нежелательно, так как не все клиенты должны или должны знать обо всех сообщениях, полученных из запроса / ответа
Что еще более важно, я, кажется, теряю класс ServiceClient, который используется для отправки сообщений, например:
// Client proxy class goes AWOL after service reference update
var client = new MyServiceReference.Client();
var responseMessage = client.ProcessRequest(requestMessage)