我试图将IMyLogger注入我的过滤器类但没有成功。这是我的代码:
属性:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public class MyActionFilterAttribute : FilterAttribute, IActionFilter
{
public IMyLogger Logger { get; set; }
public void OnActionExecuting(ActionExecutingContext filterContext) { }
public void OnActionExecuted(ActionExecutedContext filterContext) { }
}
注册:
var builder = new ContainerBuilder();
builder.RegisterModule<MyLoggerModule>();
builder.RegisterFilterProvider();
builder.RegisterType<ExtensibleActionInvoker>().As<IActionInvoker>();
IContainer AutofacContainer = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(AutofacContainer));
MyLogger模块负责注入MyLogger
public class MyLoggerModule : Autofac.Module
{
protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration)
{
registration.Preparing += (object sender, PreparingEventArgs e) => {
var type = e.Component.Activator.LimitType;
/* using reflection check if there is a constructor with
parameter of type IMyLogger and if so then create logger
and setup in constructor
*/
};
registration.Activated += (s, e) => {
var type = e.Component.Activator.LimitType;
/* using reflection check if there is a property of type
IMyLogger and if so then create logger and setup it
*/
}
}
}
问题在于,当我调试Preparing
和Activated
时,变量type
永远不会设置为MyActionFilterAttribute
并且因为执行Logger
1}}属性中的属性始终为null
有没有办法在过滤器中以这种方式设置记录器?
如果您想在此处尝试此操作,请准备并激活完整代码:
private bool HasConstructorDependencyOnLogger(Type type)
{
return type.GetConstructors()
.Any(ctor => ctor.GetParameters()
.Any(parameter => parameter.ParameterType == typeof(IMyLogger)));
}
private IEnumerable<PropertyInfo> GetLoggerProperties(Type type)
{
return type.GetProperties().Where(property => property.CanWrite &&
property.PropertyType == typeof(IMyLogger) &&
property.GetSetMethod(true).IsPublic);
}
protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration)
{
registration.Preparing += (object sender, PreparingEventArgs e) => {
var type = e.Component.Activator.LimitType;
var hasDep = HasConstructorDependencyOnLogger(type);
if (hasDep)
{
e.Parameters = e.Parameters.Concat(Enumerable.Repeat(
new ResolvedParameter(
(parameter, context) => parameter.ParameterType == typeof(ILogger),
(p, i) => new MyLogger(p.Member.DeclaringType)), 1));
}
};
registration.Activated += (s, e) =>
{
var type = e.Component.Activator.LimitType;
var properties = GetLoggerProperties(type).ToList();
if (properties.Count > 0)
{
var logger = new MyLogger(type);
foreach (var prop in properties)
{
prop.SetValue(e.Instance, logger, BindingFlags.SetProperty | BindingFlags.Instance, null, null, null);
}
}
};
}
-------更新--------
我找到了解决此问题的方法。我已从AutofacFilterProvider
继承并覆盖GetFilters
方法。我在Autofac代码中找到的是:
foreach (var filter in filters)
lifetimeScope.InjectProperties(filter.Instance);
这一行只是解析实例,并没有接受已注册的Preparing
或Activated
来电。
我的FiltersProvider看起来像这样:
public class MyAutofacFilterProvider : AutofacFilterProvider
{
public override IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
{
var filters = base.GetFilters(controllerContext, actionDescriptor).ToList();
var lifetimeScope = AutofacDependencyResolver.Current.RequestLifetimeScope;
if (lifetimeScope != null)
{
foreach (var filter in filters)
{
var actualProps = filter.Instance
.GetType()
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(pi => pi.CanWrite && pi.PropertyType == typeof(IMyLogger))
.ToList();
foreach (var actual in actualProps)
{
var setter = actual.GetSetMethod();
if (setter != null)
{
setter.Invoke(filter.Instance, new[] { new MyLogger(filter.Instance.GetType()) });
break;
}
}
}
}
}
}
此解决方案看起来很好,但每次都没有设置文件管理器中的记录器。我可以看到foreach通过set属性但后来在过滤器中为null。
这个解决方案的一个解决方案是在过滤器static
中设置Logger属性,但这不是一个完美的解决方案。你知道为什么每次都没有设置Logger吗?
答案 0 :(得分:0)
尝试使 MyActionFilterAttribute 实施 IAutofacActionFilter , 并把 builder.RegisterType()。AsWebApiExceptionFilterFor()。PropertiesAutowired() 进入你的autofact配置文件。
但MyActionFilterAttribute不再是属性