Ninject inject 注入到属性构造函数、字段或方法中

本文关键字:字段 方法 构造函数 inject 注入 属性 Ninject | 更新日期: 2023-09-27 17:56:32

我想知道以下是否可行,如果是,该怎么做。我将尝试用下面的代码来解释它。

public class RandomClass
{
    ...
    //class is filled with stuff of none importance for this demonstration
    ...
    [LogScope("Start", "End")] //The important LogScope attribute!
    public virtual void MyMethod()
    {
        ...
        //Doing something here but not the point now...
        ...
    }
    ...
}
public LogScopeAttribute : InterceptAttribute
{
    private readonly string _header;
    private readonly string _footer;
    public LogScopeAttribute(string header, string footer)
    {
        _header = header;
        _footer = footer;
        // This is just one of many constructors....
    }
    public override IInterceptor CreateInterceptor(IProxyRequest request)
    {
        return request.Context.Kernel.Get<LogScopeInterceptor>(
            new ConstructorArgument("header", _header),
            new ConstructorArgument("footer", _footer));
        // In the real version of this method there is more logic here for creating
        // the right version of the interceptor, in regards to what constrcutor the
        // LogScopeAttribute was called with.
    }
}
public class LogScopeInterceptor : SimpleInterceptor
{
    // No need to explain stuff here, (not of importance to the question)
    // but what the interceptor does for me is write to log
    // a header and footer and indent everything inside the logscope.
}

我想要的是使用 Ninject 将ILogScopeInterceptorFactory注入LogScopeAttribute,这样我就不必在 CreateInterceptor 方法中调用内核,并插入ConstructorArgument对象我想这样做...

public LogScopeAttribute : InterceptAttribute
{
    private readonly string _header;
    private readonly string _footer;
    private readonly ILogScopeInterceptorFactory _logScopeInterceptorFactory;
    public LogScopeAttribute(ILogScopeInterceptorFactory logScopeInterceptorFactory ,string header, string footer)
    {
        _header = header;
        _footer = footer;
        _logScopeInterceptorFactory = logScopeInterceptorFactory;
    }
    public override IInterceptor CreateInterceptor(IProxyRequest request)
    {
        return _logScopeInterceptorFactory.Create(_header, _footer);
    }
}

这是我与Ninject.extensions.Factory绑定的ILogScopeInterceptorFactory接口喜欢这个:

Bind<ILogScopeInterceptorFactory>().ToFactory();

public interface ILogScopeInterceptorFactory
{
    LogScopeInterceptor Create(char separatorChar, string header, string footer);
    LogScopeInterceptor Create(char separatorChar, string header);
    LogScopeInterceptor Create(string header, string footer);
    LogScopeInterceptor Create(string header);
    LogScopeInterceptor Create(char separatorChar);
    LogScopeInterceptor Create();
}

现在我想做的仍然是像这样使用LogScopeAttribute [LogScope("Start", "End")]无需手动插入工厂,只需注入即可,我该怎么做?

编辑2:

正在使用log4net登录,我在这里写下LogScopeAttribute的作用,以及输出是什么样子的。

[LogScope("The Start", "The End")]
public virtual void MyMethod()
{
    logger.Info("Hello World!");
}
OUTPUT:
logger: The Start
logger:     Hello World!
logger: The End

为了让 ninject 拦截所有方法,需要对它们进行publicvirtual。我发现这对于日志记录非常方便,可以轻松缩进方法中记录的所有内容如果我想要页眉和页脚,或者打印方法的执行时间,它都在那里。这也可以嵌套...

@FELIX

问题不在于我无法获得内核...如果我想通过调用内核来创建工厂,我可以这样做。

public override IInterceptor CreateInterceptor(IProxyRequest request)
{
    var factory = request.Context.Kernel.Get<ILogScopeInterceptorFactory>();
    return factory.Create(_header, _footer);
}

如果我手动插入工厂,我必须为每个属性执行此操作

[LogScope(_logScopeInterceptorFactory, "header", "footer")]

那只是丑陋

Ninject inject 注入到属性构造函数、字段或方法中

由于您无法像在属性中那样执行任何运行时操作...你将不得不作弊...

容器是全局的,所以我总是使用单例模式创建它......

public static class Container
{
    private static IKernel _container;
    static Container()
    {
        _container = ...; //Create the kernel and define container
    }
    public static IKernel Current { get { return _container; } }
}
public LogScopeAttribute(string header, string footer)
{
    _header = header;
    _footer = footer;
    _logScopeInterceptorFactory = Container.Current.Get<ILogScopeInterceptorFactory>();
}

当然,通常使用Container.Current.Get是一种反模式。但是,在某些情况下,这是必需的(例如属性)。在理想的世界中,属性将非常苗条-ILogScopeInterceptorFactory将完成所有工作(并且将是被测试的类)。