当前位置:  开发笔记 > 程序员 > 正文

何时何地设置自定义IOperationInvoker?

如何解决《何时何地设置自定义IOperationInvoker?》经验,为你挑选了1个好方法。

我正在尝试扩展WCF,以便我可以拥有一个RESTful Web服务,其中,对于每个操作,我执行HTTP Authorization标头的验证,其值用于调用Login()方法.

登录完成后,我希望调用操作的相应方法检查是否抛出了安全异常,在这种情况下,我将使用适当的HTTP状态代码回复自定义的"访问被拒绝"消息.

考虑到这一点,我认为实现一个IEndpointBehavior,它将IOperationInvoker的实现应用于每个操作(设置DispatchOperation.Invoker属性)将是一个好主意.

我决定使用Decorator设计模式实现IOperationInvoker.我的实现需要在其构造函数中使用另一个IOperationInvoker,方法调用将被委托给它.

这是我的IOperationInvokerImplementation:

    public class BookSmarTkOperationInvoker : IOperationInvoker{

    private readonly IOperationInvoker invoker;

    public BookSmarTkOperationInvoker(IOperationInvoker decoratee)
    {
        this.invoker = decoratee;
    }

    public object[] AllocateInputs()
    {
        return this.invoker.AllocateInputs();
    }

    public object Invoke(object instance, object[] inputs, out object[] outputs)
    {
        BeforeOperation(); // Where there's code to perform the login using WebOperationContext.Current
        object o = null;
        try
        {
            o = this.invoker.Invoke(instance, inputs, out outputs);
        }
        catch (Exception exception)
        {
            outputs = null;
            return AfterFailedOperation(exception); // Return a custom access denied response
        }

        return o;
    }

    public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state)
    {
        throw new Exception("The operation invoker is not asynchronous.");
    }

    public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result)
    {
        throw new Exception("The operation invoker is not asynchronous.");
    }

    public bool IsSynchronous
    {
        get
        {
            return false;
        }
    }
}

我决定通过扩展我已经需要的行为(WebHttpBehavior)来实现IEndpointBehavior,这样我只使用一个beavior.这是我写的代码:

public class BookSmarTkEndpointBehavior : WebHttpBehavior
{
    public override void Validate(ServiceEndpoint endpoint)
    {
        base.Validate(endpoint);
    }

    public override void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
    {
        base.AddBindingParameters(endpoint, bindingParameters);
    }

    public override void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
    {
        base.ApplyDispatchBehavior(endpoint, endpointDispatcher);

        foreach (DispatchOperation operation in endpointDispatcher.DispatchRuntime.Operations)
        {
            IOperationInvoker defaultInvoker = operation.Invoker;
            IOperationInvoker decoratorInvoker = new BookSmarTkOperationInvoker(defaultInvoker);
            operation.Invoker = decoratorInvoker;

            Console.Write("Before: " + ((object)defaultInvoker ?? "null"));
            Console.WriteLine(" After: " + operation.Invoker);
        }
    }

    public override void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
    {
        base.ApplyClientBehavior(endpoint, clientRuntime);
        throw new Exception("The BookSmarTkEndointBehavior cannot be used in client endpoints.");
    }
}

现在问题在于:

    只有在IOperationInvoker中调用构造函数,其他方法都没有.

    decoratee IOperationInvoker(在装饰器的构造函数中传递的那个)为null.

我猜测,其他一些行为的其他代码可能是之后在OperationDispatcher.Invoker设置中设置另一个IOperationInvoker.因此,压倒我的.这清楚地解释了我的情况.

发生了什么,我该怎么办?

我的服务是自托管的.

如果您需要查看它,这是我在system.serviceModel下的app.config文件中的配置.


  
    
      
        
      
    
    
    
  



  
    
      
    
  
  
    
      
      
    
  



  
    
    
  



  
    
  

我读到这里,我非常感谢你.真的很谢谢你!



1> Alexey F..:

您必须创建一个IOperationBehavior实现者,而不是在ApplyDispatchBehavior()方法中设置调用者:

 public class MyOperationBehavior: IOperationBehavior
 {
  public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
  {
  }

  public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
  {
  }

  public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
  {
   dispatchOperation.Invoker = new BookSmarTkOperationInvoker(dispatchOperation.Invoker);
  }

  public void Validate(OperationDescription operationDescription)
  {
  }
 }

然后在ApplyDispatchBehavior()中你应该设置该行为:

  public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
  {
    foreach (var operation in endpoint.Contract.Operations) {
      if (operation.Behaviors.Contains(typeof(MyOperationBehavior)))
       continue;

      operation.Behaviors.Add(new MyOperationBehavior());
   }
  }

推荐阅读
oDavid_仔o_880
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有