更新的答案-
看了你的评论,我明白了。因此,您想提供字符串,然后在 OperationInovker 出现之前对其进行转换。所以我弄脏了手,终于做到了。
这是我所做的。一个派生自它的新类WebHttpBehavior
将提供一个我们可以扩展或覆盖现有行为的地方WebHttpBidning
。
public class MyWebHttpBehavior : WebHttpBehavior
{
}
虽然这是一个黑客,但这会奏效。Typed 参数的问题是 URL 模板格式化程序通过检查类型的方法签名来抛出异常,string
所以我通过覆盖BindingInformation
by overiding 方法来摆脱它GetRequestDispatchFormatter
。
protected override IDispatchMessageFormatter GetRequestDispatchFormatter(OperationDescription operationDescription, ServiceEndpoint endpoint)
{
foreach (var item in operationDescription.Messages[0].Body.Parts)
{
item.Type = typeof(string);
}
return base.GetRequestDispatchFormatter(operationDescription, endpoint);
}
应用此行为后,运行时将不再为字符串参数检查抛出异常。现在我需要更改 OperationInvoker,因为如果您运行它,那么当您从客户端调用操作时,这将引发异常Invalid cast
。
现在来了IOperationInvoker
图片。我只是从类型 object 的 input[] 中获取值,将值从String
to转换为Guid
并将其传递回 Invoker。
public class ValueCastInvoker : IOperationInvoker
{
readonly IOperationInvoker _invoker;
public ValueCastInvoker(IOperationInvoker invoker)
{
_invoker = invoker;
}
public ValueCastInvoker(IOperationInvoker invoker, Type type, Object value)
{
_invoker = invoker;
}
public object[] AllocateInputs()
{
return _invoker.AllocateInputs().ToArray();
}
private object[] CastCorrections(object[] inputs)
{
Guid obj;
var value = inputs[0] as string;
if (Guid.TryParse(value, out obj))
{
return new[] { (object)obj }.Concat(inputs.Skip(1)).ToArray();
}
return inputs.ToArray();
}
public object Invoke(object instance, object[] inputs, out object[] outputs)
{
return _invoker.Invoke(instance, CastCorrections(inputs), out outputs);
}
public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state)
{
return _invoker.InvokeBegin(instance, 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; }
}
}
现在我花了很长时间才弄清楚如何在管道中注入这个自定义操作 inovker。我在这里找到了相关的 stackoverflow 答案。并实施了人们建议的方式,并且奏效了。
在此处添加摘要:必须实现新的 IOperationBehavior 并将其附加到 DispatcherRuntime。
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 ValueCastInvoker(dispatchOperation.Invoker);
}
public void Validate(OperationDescription operationDescription)
{
}
}
现在在 MyWebHttpBehavior 中重写ApplyDispatchBehavior
并引入上面实现的IOperationBehavior
。
public override 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());
}
base.ApplyDispatchBehavior(endpoint, endpointDispatcher);
}
现在所有这些黑客和扩展都会使这个合法。
[WebInvoke(Method = "GET", UriTemplate = "/{id}")]
string GetValue(Guid id);
免责声明:我在试验这种扩展和应用自定义行为时很开心,但我没有检查受影响的区域。因此,使用它需要您自己承担风险,并且可以随意更改/增强。对不起错别字。
更新 2
我创建了一个库来包装这个 web http 行为扩展。该库在方法参数(多个)中提供了对其他值类型的更多支持。看看这个。