我想知道以下是否可行,如果是,如何做到这一点。 我会尝试用下面的代码解释它。
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);
}
}
这是我与ILogScopeInterceptorFactory
绑定的Ninject.extensions.Factory
界面
像这样:
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")]
无需手动插入工厂,只需注入它,我该怎么做?
EDIT2:
我正在使用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拦截所有方法,它们必须是public
和virtual
。
我发现这对于日志记录非常方便,很容易缩进方法中记录的所有内容
如果我想要一个页眉和页脚,或打印该方法的执行时间,那就在那里。
这也可以嵌套......
@FELIX
问题不在于我无法获得内核...... 如果我想通过调用内核来创建工厂,我就可以这样做。
public override IInterceptor CreateInterceptor(IProxyRequest request)
{
var factory = request.Context.Kernel.Get<ILogScopeInterceptorFactory>();
return factory.Create(_header, _footer);
}
如果我手动插入工厂,我必须为每个属性
执行此操作[LogScope(_logScopeInterceptorFactory, "header", "footer")]
那只是简单的uggly
答案 0 :(得分:0)
由于你不能在属性中做任何运行时...你将不得不作弊...
容器是全局的,所以我总是使用单例模式创建它......
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
将完成所有工作(并且将是经过测试的类)。