Расширение WCF для регистрации и выполнения действий для каждого метода. IErrorHandler не имеет понятия о методе?

У меня есть нормальный сервис WCF с несколькими методами.

Я хотел бы записать некоторую информацию и выполнить некоторые действия в начале метода и в конце.

Осуществляя IParameterInspector Я могу легко сделать много регистрации. методы BeforeCall а также AfterCall дай мне почти все, что мне нужно.

Но это не работает для исключений. Есть IErrorHandler, что позволяет мне выполнить некоторую обработку, если произошло исключение. Недостатком является то, что я не знаю, из какого метода он был брошен. Все потому что IErrorHandler привязан к служебному поведению, а не к самой операции.

Тем не менее, я могу получить имя метода, используя код ниже:

((System.Reflection.RuntimeMethodInfo)(exception.TargetSite)).Name == "MyMethod"

Это не выглядит хорошей идеей для меня.

Вопрос: Ребята, есть ли другие расширения WCF, которые я могу использовать для достижения своей цели? Вы бы порекомендовали использовать старый приятель try-catch и, возможно, обернуть его в какой-нибудь приятный синтаксис, чтобы я мог выполнять действия в начале и в конце? Какой будет синтаксис? Что вы используете для подобных целей?

Спасибо вперед.

3 ответа

Решение

Как насчет IOperationInvoker?

public class NHibernateOperationInvoker : IOperationInvoker {
    private readonly IOperationInvoker _invoker;
    private readonly String _operationName;

    public NHibernateOperationInvoker(IOperationInvoker invoker, String operationName) {
        _invoker = invoker;
        _operationName = operationName;
    }

    public Object[] AllocateInputs() {
        return _invoker.AllocateInputs();
    }

    public Object Invoke(Object instance, Object[] inputs, out Object[] outputs) {
        using (var context = NHibernateContext.CreateNew()) {
            try {
                var result = _invoker.Invoke(instance, inputs, out outputs);
                context.Commit();
                return result;
            } catch(Exception ex) {
                Debug.Fail("Operation " + _operationName + " failed with " + ex.Message);
            }
        }
    }

    public IAsyncResult InvokeBegin(Object instance, Object[] inputs, AsyncCallback callback, Object state) {
        throw new NotImplementedException("NHibernateOperationInvoker.InvokeBegin");
    }

    public Object InvokeEnd(Object instance, out Object[] outputs, IAsyncResult result) {
        throw new NotImplementedException("NHibernateOperationInvoker.InvokeEnd");
    }

    public Boolean IsSynchronous {
        get { return true; }
    }
}

Это связано с использованием IOperationBehavior, который делает dispatchOperation.Invoker = new NHibernateOperationInvoker(dispatchOperation.Invoker, dispatchOperation.Name);

Я не знаю каких-либо расширений, которые позволят достичь того, что вы хотите, и вот обширный список. IErrorHandler - это прекрасный способ обработки того, что вам нужно.

Не засоряйте свой код с помощью try/catch. Try/Catch подразумевает, что вы будете выполнять некоторую логику компенсации, и регистрация не попадает в эту категорию.

Я не уверен, зачем вам нужен актерский состав или почему вы проверяете на равенство. Использование метода информация в порядке. Другой вариант - использование класса StackTrace для получения информации о каждом отдельном вызове, например

 public void ProvideFault(Exception error, MessageVersion version, ref Message fault)
        {
            var s = new StackTrace(error);
            var faultyTowers = s.GetFrame(0);

        }

Одна вещь, которую нужно учитывать, это что-то вроде PostSharp, но это не бесплатно ($ и производительность). Вы можете вводить аспект АОП вокруг каждого вызова, который вы можете использовать для чего угодно.

Вы должны постараться, чтобы ваш обработчик ошибок не делал слишком много.

То, что вы хотите, это IDispatchMessageInspector

Если что-то отправлено обратно клиенту, будет вызван BeforeSendReply. Это работает, если вы добавите его в dispatchRuntime в качестве MessageInspector:

public class MessageLogger : IDispatchMessageInspector
{
    public object AfterReceiveRequest( ref System.ServiceModel.Channels.Message request, IClientChannel channel, InstanceContext instanceContext )
    {
        Log("Begin: " + request.Headers.Action );
        return request;
    }

    public void BeforeSendReply( ref System.ServiceModel.Channels.Message reply, object correlationState )
    {
        System.ServiceModel.Channels.Message request = (System.ServiceModel.Channels.Message)correlationState;
        Log("End: " + request.Headers.Action );
    }
}

Недостатком является то, что вы смотрите на необработанные сообщения. Они сопоставляются с операциями, которые реализует ваш сервис.

Другие вопросы по тегам