使用IOperationBehavior提供WCF参数

时间:2010-06-15 13:11:14

标签: wcf

这是我进入stackoverflow世界的第一步,如果我提出任何建议,请道歉。

我正在尝试创建一个WCF操作,该操作的参数不会暴露给外部世界,而是自动传递给函数。

所以全世界都看到了这一点:int Add(int a, int b)

但它实现为:int Add(object context, int a, int b)

然后,系统在运行时提供上下文。我正在使用的例子是完全人为的,但模仿我在现实场景中正在研究的东西。

我能够接近,但并不是那么完整。

首先,我创建了一个简单的方法并编写了一个应用程序来确认它的工作原理。确实如此。它返回一个+ b并将上下文作为字符串写入我的调试。耶。

    [OperationContract]
    int Add(object context, int a, int b);
然后我写了下面的代码:

public class SupplyContextAttribute : Attribute, IOperationBehavior
{
    public void Validate(OperationDescription operationDescription)
    {
        if (!operationDescription.Messages.Any(m => m.Body.Parts.First().Name == "context"))
            throw new FaultException("Parameter 'context' is missing.");
    }

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

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

    public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
    {
        // Remove the 'context' parameter from the inbound message
        operationDescription.Messages[0].Body.Parts.RemoveAt(0);
    }
}

public class SupplyContextInvoker : IOperationInvoker
{
    readonly IOperationInvoker _invoker;

    public SupplyContextInvoker(IOperationInvoker invoker)
    {
        _invoker = invoker;
    }

    public object[] AllocateInputs()
    {
        return _invoker.AllocateInputs().Skip(1).ToArray();
    }

    private object[] IntroduceContext(object[] inputs)
    {
        return new[] { "MyContext" }.Concat(inputs).ToArray();
    }

    public object Invoke(object instance, object[] inputs, out object[] outputs)
    {
        return _invoker.Invoke(instance, IntroduceContext(inputs), out outputs);
    }

    public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state)
    {
        return _invoker.InvokeBegin(instance, IntroduceContext(inputs), callback, state);
    }

    public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result)
    {
        return _invoker.InvokeEnd(instance, out outputs, result);
    }

    public bool IsSynchronous
    {
        get { return _invoker.IsSynchronous; }
    }
}

我的WCF操作现在看起来像这样:

    [OperationContract, SupplyContext]
    int Amend(object context, int a, int b);

我更新的参考文献不再显示'context'参数,这正是我想要的。

问题是,当我运行代码时,它会越过AllocateInputs,然后在WCF内容的某处抛出Index was outside the bounds of the Array.错误。

我尝试了其他的东西,我发现我可以成功更改参数的类型并重命名它并让我的代码工作。但是,当我删除参数时,它就会崩溃。

任何人都可以告诉我如何让它工作(或者如果它可以完成)。

1 个答案:

答案 0 :(得分:5)

好吧,我自己想出来了。 MessagePartDescription具有Index属性。我只需要重新调整这些值。

    public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
    {
        var parts = operationDescription.Messages[0].Body.Parts;
        parts.RemoveAt(0);
        for (int i = 0; i < parts.Count; i++)
            parts[i].Index = i;
    }