WCF: извлечение MethodInfo из OperationContext
Есть ли элегантный способ получить метод, который будет выполняться в экземпляре службы из MessageInspector/AuthorizationPolicy/другой точки расширения? Я мог бы использовать
OperationContext.Current.IncomingMessageHeaders.Action
но я надеюсь, что есть способ сделать это без ручного согласования действий SOAP с OperationContracts.
То, что я пытаюсь сделать, это проверить атрибуты метода до его выполнения.
Ответы
Ответ 1
Это заняло у меня навсегда, но я нашел способ, который лучше, чем поиск и провал через весь контракт:
string action = operationContext.IncomingMessageHeaders.Action;
DispatchOperation operation =
operationContext.EndpointDispatcher.DispatchRuntime.Operations.FirstOrDefault(o =>
o.Action == action);
// Insert your own error-handling here if (operation == null)
Type hostType = operationContext.Host.Description.ServiceType;
MethodInfo method = hostType.GetMethod(operation.Name);
И вот вы. Вы можете получить атрибуты или сделать все, что вам нравится.
Примечание. Возможно, у вас возникнет соблазн попытаться использовать OperationSelector в DispatchRuntime. Проблема, которую я обнаружил, заключалась в том, что в моем случае, на конкретном этапе обработки, OperationSelector был пустой ссылкой. Если у вас есть доступ к этому свойству, он, вероятно, более быстрый и надежный в использовании, чем "сканирование" OperationCollection, как указано выше.
Ответ 2
Если OperationContext.CurrentIncomingMessageHeaders.Action
имеет значение null, вы можете сделать это - это немного терпение:
string actionName = OperationContext.Current.IncomingMessageProperties["HttpOperationName"] as string;
Type hostType = operationContext.Host.Description.ServiceType;
MethodInfo method = hostType.GetMethod(actionName);
Ответ 3
На основе ответов @Aaronaught и @TimDog и этот вопрос SO я придумал решение, которое должно работать как для REST, так и для SOAP.
///<summary>Returns the Method info for the method (OperationContract) that is called in this WCF request.</summary>
System.Reflection.MethodInfo GetActionMethodInfo(System.ServiceModel.OperationContext operationContext ){
string bindingName = operationContext.EndpointDispatcher.ChannelDispatcher.BindingName;
string methodName;
if(bindingName.Contains("WebHttpBinding")){
//REST request
methodName = (string) operationContext.IncomingMessageProperties["HttpOperationName"];
}else{
//SOAP request
string action = operationContext.IncomingMessageHeaders.Action;
methodName = operationContext.EndpointDispatcher.DispatchRuntime.Operations.FirstOrDefault(o =>o.Action == action).Name;
}
// Insert your own error-handling here if (operation == null)
Type hostType = operationContext.Host.Description.ServiceType;
return hostType.GetMethod(methodName);
}
Ответ 4
Функция интеграции WCF Castle позволяет вам делать это (среди многих полезных вещей) с помощью прокси-серверов DynamicProxy.
Посмотрите здесь.
Там не так много документации, поэтому для документов о том, как их использовать, лучше всего взглянуть на его тесты.