代码之家  ›  专栏  ›  技术社区  ›  Chris Kemp

使用IOperationBehavior提供WCF参数

wcf
  •  7
  • Chris Kemp  · 技术社区  · 15 年前

    这是我进入stackoverflow世界的第一步,如果我搞砸了什么,我深表歉意。

    我正在尝试创建一个WCF操作,它有一个参数,该参数不对外公开,而是自动传递到函数中。

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

    但其实施方式如下: int Add(object context, int a, int 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 然后抛出一个 Index was outside the bounds of the Array. 在WCF内部的某个地方出错。

    我尝试过其他方法,我发现我可以成功地更改参数的类型并重命名它,然后让代码正常工作。但是当我去掉参数的时候,它就掉下来了。

    有没有人能告诉我一些如何让这项工作(或者如果它可以做的话)的想法。

    1 回复  |  直到 15 年前
        1
  •  5
  •   Chris Kemp    15 年前

    我自己想出来的。MessagePartDescription具有索引属性。我只需要重新同步这些值。

        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;
        }
    
    推荐文章