通过城堡动态代理使用非空构造函数的Ninject拦截代理类 [英] Ninject interception proxying class with non empty constructor via castle dynamic proxy

查看:91
本文介绍了通过城堡动态代理使用非空构造函数的Ninject拦截代理类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前的大部分实施都基于此处提供的信息:

I am basing most of my current implementation off the information provided here:

Ninject拦截具有某些属性的任何方法吗?

我使用一个自定义计划策略类,该类将查找具有给定属性(而不是ninject拦截器属性)的所有方法,如果符合条件,这些方法将被代理.

I use a custom planning strategy class which looks for all methods with given attributes (not ninject interceptor attributes) which will then get proxied if it matches the criteria.

用法示例为:

Kernel.Components.Add<IPlanningStrategy, CustomPlanningStrategy<LoggingAttribute, LoggerInterceptor>>();

然后它将查找具有[Logging]属性的任何方法,然后将使用日志记录拦截器.

This would then look for any methods which have a [Logging] attribute and will then use the logging interceptor.

但是,当它试图代理具有相关属性的方法时,我目前正在从动态代理获取InvalidProxyConstructorArgumentsException.现在,我记得读过您需要虚方法,但是我不记得看到您有一个无参数构造函数.

However I am currently getting InvalidProxyConstructorArgumentsException from dynamic proxy when it is trying to proxy the methods with related attributes on. Now I remember reading that you need virtual methods, however I do not remember seeing that you HAD to have a parameterless constructor.

所有绑定都是针对接口完成的,并且AOP拦截器通过属性和上面链接中提到的自定义代理计划类发生.

All bindings are done against interfaces, and the AOP interceptors happen via attributes and the custom proxy planning class mentioned in the link above.

那么有没有一种方法可以获取动态代理(或linfu版本)来代理具有依赖项的构造函数的类? (所有依赖项都在内核中,因此无法解决它们).

So is there a way to get dynamic proxy (or the linfu version) to proxy the classes which have constructors with dependencies? (All dependencies are in the Kernel so its not like they cannot be resolved).

推荐答案

另一种方法是对所有具有基于[Logging]属性的方法的类使用基于约定的绑定.但是,这意味着向方法中添加[Logging]属性将影响对象的绑定,这可能是不希望的.

An alternate approach would be to use a convention based binding for all classes with a method with a [Logging] attribute. However, this means that adding a [Logging] attribute to a method will influence the binding of the object, which may be undesired.

这就是它的工作方式(已验证工作):

So this is how it would work (verified to work):

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public sealed class LoggingAttribute : Attribute
{
}

public interface IClassNotToBeIntercepted
{
    void DoSomething();
}

public class ClassNotToBeIntercepted : IClassNotToBeIntercepted
{
    public void DoSomething() { }
}

public interface IClassToBeIntercepted
{
    void DoNotLogThis();
    void LogThis();
    void LogThisAsWell();
}

public class ClassToBeIntercepted : IClassToBeIntercepted
{
    public void DoNotLogThis() { }

    [Logging]
    public void LogThis() { }

    [Logging]
    public void LogThisAsWell() { }
}

public class LoggingInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        Console.WriteLine("interceptor before {0}", BuildLogName(invocation));

        invocation.Proceed();

        Console.WriteLine("interceptor after {0}", BuildLogName(invocation));
    }

    private static string BuildLogName(IInvocation invocation)
    {
        return string.Format(
            "{0}.{1}", 
            invocation.Request.Target.GetType().Name,
            invocation.Request.Method.Name);
    }
}

public class DemoModule : NinjectModule
{
    public override void Load()
    {
        this.Bind(convention => convention
            .FromThisAssembly()
            .SelectAllClasses()
            .Where(ContainsMethodWithLoggingAttribute)
            .BindDefaultInterface()
            .Configure(x => x
                .Intercept()
                .With<LoggingInterceptor>()));

        this.Bind<IClassNotToBeIntercepted>()
            .To<ClassNotToBeIntercepted>();
    }

    private static bool ContainsMethodWithLoggingAttribute(Type type)
    {
        return type
            .GetMethods()
            .Any(method => method.HasAttribute<LoggingAttribute>());
    }
}

和测试:

    [Fact]
    public void InterceptorTest()
    {
        var kernel = new StandardKernel();
        kernel.Load<DemoModule>();

        kernel.Get<IClassNotToBeIntercepted>()
            .DoSomething();

        kernel.Get<IClassToBeIntercepted>()
            .LogThis();
    }

结果将显示以下控制台输出:

Results in the following console output:

interceptor before ClassToBeIntercepted.LogThis
interceptor after ClassToBeIntercepted.LogThis

这篇关于通过城堡动态代理使用非空构造函数的Ninject拦截代理类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆