这是我进入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);
Run Code Online (Sandbox Code Playgroud)
然后我写了下面的代码:
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; }
}
}
Run Code Online (Sandbox Code Playgroud)
我的WCF操作现在看起来像这样:
[OperationContract, SupplyContext]
int Amend(object context, int a, int b);
Run Code Online (Sandbox Code Playgroud)
我更新的参考文献不再显示"context"参数,这正是我想要的.
麻烦的是,当我运行代码时,它会超过AllocateInputs,然后Index was outside the bounds of the Array.在WCF内部的某个地方抛出错误.
我尝试了其他的东西,我发现我可以成功地更改参数的类型并重命名它并让我的代码工作.但是,当我删除参数时,它就会失败.
任何人都可以给我一些关于如何使其工作的想法(或者如果它可以完成).
好吧,我自己想出来了.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;
}
Run Code Online (Sandbox Code Playgroud)