Как использовать Autofac с DynamicProxy для определения пространства имен целевого прокси-класса

Я использую IInterceptor для перехвата вызовов методов в определенных классах. Перехватчик устанавливается следующим образом: открытый класс InstrumentationInterceptor: IInterceptor { public InstrumentationInterceptor() { Measure.Configure(new StatsdConfig()); }

    public void Intercept(IInvocation invocation)
    {
        var instrumentationId = new StringBuilder();
        instrumentationId.Append(typeof(Program).Namespace.Replace(".", string.Empty).ToLower());
        instrumentationId.Append(".");
        instrumentationId.Append("response");
        instrumentationId.Append(".");
        // The following will split the camel case simple name of the proxied class,
        //  where 'Consumer' suffix has been removed, and also convert to lower case
        instrumentationId.Append(Regex.Replace(invocation.TargetType.Name.Replace("Consumer", string.Empty), "(\\B[A-Z])", "_$1").ToLowerInvariant());
        instrumentationId.Append(".");
        instrumentationId.Append("duration");
        using (
            Measure.StartTimer(instrumentationId.ToString()))
        {
            invocation.Proceed();
            Measure.Counter(instrumentationId.ToString(), 1);
        }
    }
}

Это тогда связано как в модуле Autofac:

var builder = new ContainerBuilder();
builder.RegisterType<DataConsumer>().
            As<IConsumer<DataRequest>>().
            EnableInterfaceInterceptors().
            InterceptedBy(typeof (InstrumentationInterceptor));
builder.Build();

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

Любые мысли по этому поводу будут полезны.

Благодарю.

2 ответа

Решение

Вы можете использовать GetConcreteMethodInvocationTarge метод в вызове, чтобы получить MethodInfo экземпляр, который вы на самом деле перехватывают.

GetConcreteMethodInvocationTarget:

  • Резюме: возвращает конкретный экземпляр IInvocation.MethodInvocationTargetс любыми общими параметрами, связанными с реальными типами. Для интерфейсных прокси это будет указывать на System.Reflection.MethodInfo в целевом классе.
  • Возвращает: конкретная реализация IInvocation.MethodInvocationTarget, или же IInvocation.MethodInvocationTarget если не универсальный метод.

С MethodInfo Вы можете получить тип, а затем пространство имен.

String namespace = invocation.GetConcreteMethodInvocationTarget().DeclaringType.Namespace;

Другое решение было бы использовать InvocationTarget собственность, а затем вызывая .GetType() метод для получения перехваченного типа, но в некоторых сложных случаях он может не работать.

String namespace = invocation.InvocationTarget.GetType().Namespace;

ОК, это было проще, чем я думал.

invocation.InvocationTarget.ToString() 

дает вам пространство имен целевого класса; как следует из названия:)

Спасибо

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