У меня есть идея, но мне нужна помощь в ее реализации.
WCF не поддерживает делегатов в своих контрактах.Вместо этого он имеет громоздкий механизм контрактов обратного вызова, и я ищу способ преодолеть это ограничение.
Я думал об использовании IDataContractSurrogate
для замены каждого делегата в контракте токеном, который будет сериализованк удаленной конечной точке.Там токен будет десериализован в сгенерированный делегат.Этот сгенерированный делегат отправит общее сообщение обратного вызова, которое инкапсулирует все аргументы (с которыми был вызван делегат).
Общее сообщение обратного вызова достигнет первой конечной точки, и там исходный делегат будет вызван с аргументами.
Вот целевая (упрощенная) последовательность:
- A вызывает B-proxy.Foo (обратный вызов)
- обратный вызов сериализуется через DelegateSurrogate.
- DelegateSurrogate сохраняет делегата в выделенном хранилище делегатов и заменяет его токеном
- Сообщение поступает в конечную точку B
- токен десериализуется через DelegateSurrogate
- DelegateSurrogate создает сгенерированный делегат
- B.Foo (генерируется обратный вызов) вызывается
- Позже B вызывает генерируемый вызов возврата (аргументы)
- generateCallback (аргументы) вызывает выделенный общийконтракт на конечной точке A: CallbackContract-proxy.GenericCallback (args)
- CallbackContract.GenericCallback (args) вызывается в конечной точке A
- Исходный обратный вызов извлекается из хранилища и вызывается: callback (args)
Я уже реализовал это ранее, используя службуавтобус (NServiceBus
), но я хочу адаптировать идею к WCF, и мне трудно.Я знаю, как реализовать шаги 3, 6, 9 и 11. Я пока не знаю, как связать все в WCF - особенно суррогатную часть.
Вот и все - надеюсь, мой вопрос имел смысл, и чтоКоллективная мудрость здесь сможет помочь мне построить это.
Вот пример использования моего желаемого решения:
// client side
remoteSvc.GetEmployeeById(17, emp =>
{
employees.Add(emp);
logger.log("Result received");
});
// server side
public void GetEmployeeById(int id, Action<Employee> callback)
{
var emp = getEmpFromDb(id);
callback(emp);
}