Какую точку расширения WCF следует использовать для установки контекста для каждой операции?
Я хочу настроить окружающий контекст (аналогично тому, как работает Thread.CurrentPrincipal) для каждой операции всех служб, работающих внутри хоста.
Какой механизм расширения я должен использовать? Их много, поэтому я в замешательстве, так как практически не имею опыта работы с WCF.
1 ответ
Решение
Вот решение:
Сначала мы создаем поведение конечной точки, которое добавляет инициализаторы к операциям:
public class CallContextInitializerBehavior : IEndpointBehavior
{
private readonly ICallContextInitializer callContextInitializer;
private ServiceHost serviceHost;
public CallContextInitializerBehavior(ICallContextInitializer callContextInitializer)
{
this.callContextInitializer = callContextInitializer;
}
public void AddToHost(ServiceHost host)
{
// only add to host once
if (this.serviceHost != null)
{
return;
}
this.serviceHost = host;
foreach (ServiceEndpoint endpoint in this.serviceHost.Description.Endpoints)
{
endpoint.Behaviors.Add(this);
}
}
public void Validate(ServiceEndpoint endpoint)
{
}
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
{
foreach (DispatchOperation operation in endpointDispatcher.DispatchRuntime.Operations)
{
operation.CallContextInitializers.Add(callContextInitializer);
}
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
}
}
Затем мы создаем нашу собственную реализацию ICallContextInitializer:
public class MyCallContextInitializer : ICallContextInitializer
{
public object BeforeInvoke(InstanceContext instanceContext, IClientChannel channel, Message messa
{
...do domething here...
return myCorrelationState; // or null if not important;
}
public void AfterInvoke(object correlationState)
{
UserInfo userInfoBeforeInvoke = (UserInfo) correlationState;
AmbientContext.Context.SetCurrent(userInfoBeforeInvoke);
}
}
Наконец, примените поведение с помощью вызова (конечно, лучше использовать IoC):
var initializer = new MyCallContextInitializer();
var behavior = new CallContextInitializerBehavior(initilizer);
behvior.AddToHost(serviceHost);