Значи искаш да подадеш низа и да го преработиш преди да се включи OperationInovker. Поизцапах си ръцете, но накрая го подкарах.
Ето какво направих. Нов клас наследява WebHttpBehavior, което ни дава възможност да разширим или променим поведението на WebHttpBidning.
public class MyWebHttpBehavior : WebHttpBehavior
{
}
Въпреки, че е малко хакче, трябва да работи. Проблема с типизирания аргумент е, че форматирането на URL шаблона хвърля exception като проверява метода за тип string, така че го разкарах като промених BindingInformation чрез override-ване на метода 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);
}
След прилагането на това поведение, повече няма да се хвърля exception при проверката за string аргумент. Сега трябва да се промени OperationInvoker, защото тогава той ще хвърля exception(Invalid cast),когато извикаш операцията от клиента.
И ето го IoperationInvoker. Просто взех стойността от input[] като в тип обект, конвертирах от string в guid и го подадох обратно на Invoker.
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; }
}
}
Това,което ми отне доста време, беше да измисля как да инжектирам този персонализиран invoker в основния код.
Трябва да се имплементира нов 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 правя override на ApplyDispatchBehavior и вкарвам горе имплементирания ApplyDispatchBehavior.
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);