使用EnableClassInterceptors和WithParameter注册类型

时间:2015-12-17 19:15:13

标签: autofac

我遇到Autofac问题,似乎EnableClassInterceptors干扰了我使用.WithParameter(...)的能力。使用下面的代码在Service上调用构造函数时,不会填充someString。注意:

  • 我尝试过使用ResolvedParameter,它没有帮助(注意:我的Resolved参数在我尝试时仍然包含参数的名称)
  • 如果我删除EnableClassInterceptors和InterceptedBy,则参数会正确填充。然而,由于我需要拦截器,因此这不是一个有效的解决方案。
  • 重新排序WithParameter,EnableClassInterceptors和InterceptedBy没有帮助。
  • 查看Type Interceptors,特别是" Class Interceptors和UsingConstructor"在docs.autofac.org上,它提到使用EnableClassInterceptors会导致ConstructUsing失败。我认为下面的方案可能会发生类似的情况。

我的注册码片段如下所示:

var builder = new ContainerBuilder();

builder.RegisterType<Dependency>.As<IDependency>.InstancePerLifetimeScope();

builder.RegisterType<Service>()
    .As<IService>()
    .WithParameter(new NamedParameter("someString", "TEST"))
    .EnableClassInterceptors()
    .InterceptedBy(typeof(LogExceptionsInterceptor));

Service的构造函数看起来像这样:

public class Service : IService
{
    public Service(IDependency dependency, string someString)
    {
        if(dependency == null) 
            throw ArgumentNullException(nameof(dependency));
        if(someString == null) 
            //**throws here**
            throw ArgumentNullException(nameof(someString)); 
    }   
}

[猜猜] 我想到的是,当调用EnableClassInterceptors时,会生成一个代理类,其构造函数在现有的构造函数之上,但参数名称不要复制到代理类/构造函数中。

这是一个问题吗?有没有办法形成允许同时使用WithParameter和EnableClassInterceptors的注册?这是Autofac中的错误吗?

1 个答案:

答案 0 :(得分:2)

您的猜测是正确的:生成的代理类不保留构造函数参数名称。

目前没有办法在DynamicProxy中影响它,所以这不是Autofac的错误(尽管Autofac文档网站上没有记录此边缘情况)。

这是您的原始Service课程参数的样子:

typeof(Service).GetConstructors()[0].GetParameters()
{System.Reflection.ParameterInfo[2]}
    [0]: {ConsoleApplication10.IDependency dependency}
    [1]: {System.String someString}

但生成的代理不保留名称:

GetType().GetConstructors()[0].GetParameters()
{System.Reflection.ParameterInfo[3]}
    [0]: {Castle.DynamicProxy.IInterceptor[] }
    [1]: {ConsoleApplication10.IDependency }
    [2]: {System.String }

因此,您有两个不太强大的选项可以使用WithParameter来解决此限制:

  • 使用TypedParamterstring作为类型:

    .WithParameter(new TypedParameter(typeof(string), "TEST"))
    

    但是,如果你有多个相同类型的参数,那么它将无法运作

  • 在这种情况下使用PositionalParameter如果代理类型需要添加1

    .WithParameter(new PositionalParameter(2, "TEST"))
    

另一个选择是不使用原始字符串类型,但创建一个包装器,例如MyServiceParameter或创建另一项服务,可以为您的其他服务提供这些string配置值。

相关问题