Это мой первый шаг в мир переполнения стека, поэтому прошу прощения, если я что-нибудь исправлю.
Я пытаюсь создать операцию WCF, у которой есть параметр, который не отображается во внешнем мире, но вместо этого автоматически передается в функцию.
Итак, мир видит это: int Add(int a, int b)
Но это реализовано так: int Add(object context, int a, int b)
Затем контекст предоставляется системой во время выполнения. Пример, с которым я работаю, полностью искусственный, но имитирует то, с чем я сталкиваюсь в реальном сценарии.
Я могу приблизиться, но не совсем так.
Прежде всего, я создал простой метод и написал приложение, чтобы подтвердить, что он работает. Оно делает. Он возвращает + b и записывает контекст в виде строки для моей отладки. Yay.
[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.
Я пробовал другие вещи, и я обнаружил, что могу успешно изменить тип параметра, переименовать его и заставить мой код работать. Но в тот момент, когда я удаляю параметр, он падает.
Может ли кто-нибудь дать мне некоторое представление о том, как заставить это работать (или если это можно сделать вообще).