Какую точку расширения 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); 
Другие вопросы по тегам