Использование RealProxy для переноса нескольких соединений WCF
Я работаю над проектом, в котором наш сервер взаимодействует с несколькими серверами, имеющими один и тот же интерфейс (как при кластеризации). Мы используем циклический перебор, чтобы выбрать сервер для отправки нашего запроса. До сих пор мы использовали Expression для вызова нашего ClusterManager, но это приводит к некоторому уродливому коду. Это также усложняет юнит-тесты и немного затрудняет проверку параметров метода. Это также может привести к некоторым проблемам с Moq со случайными исключениями (не тема для этого поста).
В настоящее время я вызываю сервер и юнит-тест, как описано в пост- настройке Moq для интерфейса с аргументами действия или функции
На точку:
В настоящее время у меня есть следующий подход:
public interface IServerAdapter
{
void CallServer(Expression<Action<IServerExposingToClient>> methodToCall, out bool serverCalled);
}
private void DoSomething()
{
MainViewModel.ServerAdapter.CallServer(server => server.SaveServerSettings(ServerSettings));
}
Я хочу изменить это следующим образом:
public interface IServerAdapter
{
IServerExposingToClient ServerProxy { get; }
}
private void DoSomething()
{
MainViewModel.ServerAdapter.ServerProxy.SaveServerSettings(ServerSettings);
}
ServerProxy - это RealProxy, и мне нужно перевести этот вызов в ClusterManager для выполнения фактического вызова на сервер. В настоящее время ClusterManager имеет те же подписи для CallServer, который немного избыточен для существующей реализации. Для перевода звонка в Invoke(IMessage) у меня есть две идеи.
Идея 1 Переведите IMethodCallMessage в выражение lamda (которое я не смог выяснить, как это сделать) и передайте его ClusterManager. За исключением проблемы, я не знаю, как создать выражение, а затем снова обработать возвращаемое значение. Некоторые методы возвращают значение, а другие нет, поэтому это включает в себя сохранение нескольких перегрузок ClusterManager.CallServer. Мне также нужно создать IMessage, чтобы вернуться из Invoke.
Идея 2 Получить RealProxy из TransparentProxy соединения WCF, которое я сейчас использую для вызова сервера, и напрямую вызвать Invoke с сообщением, которое у меня есть. В моем испытании (с использованием интеграционного теста) я, по-видимому, могу успешно вызвать сервер, но просматривая ReturnMessage, возвращаемого значения нет, а свойству Exception присваивается значение ArithmetricException, когда ServiceChannelProxy пытается получить данные сообщения. Это может быть связано либо с тем, что я сделал что-то не так в своем тесте, либо с тем, что я не могу использовать один и тот же LogicalCallContext (или что-то еще) на двух отдельных прокси.
Любые указатели о том, как с этим бороться? Я предпочитаю идею 2, так как она кажется самой простой и, надеюсь, приведет к наименьшему объему кода. Реализация всех методов в IServerExposingToClient в классе для вызова на правильном сервере - это не то, что я хотел бы сделать.
Любые указатели о том, как с этим бороться?
1 ответ
Используя информацию, найденную здесь, я смог решить проблему. В приведенном ниже коде proxy является объектом ICommunicationObject для канала к службе WCF. Кажется, работает довольно хорошо.
public override IMessage Invoke(IMessage msg)
{
var methodCall = (IMethodCallMessage)msg;
var proxy = FindNextProxy();
try
{
MethodBase methodBase = methodCall.MethodBase;
object[] args = methodCall.Args;
object returnValue = methodBase.Invoke(proxy, args);
return CreateReturnMessage(returnValue, methodCall);
}
catch (TargetInvocationException ex)
{
return CreateReturnMessage(ex.InnerException, methodCall);
}
}