如何只使用Autofac注入一些构造函数参数并结合使用InjectionModule

时间:2011-05-31 06:19:59

标签: .net registration autofac

要点:

如何在注册时将注入模块与常规contain.Resolve()电话结合起来?

  

〜更新(5小时后和反馈后)〜:

     

使用 RegisterType<> 而不是   到 Register()无法解决问题   我所拥有的实际复杂程度   生产代码,我已经更新了   BitBucket上的演示代码包含泛型    ISecond ,示例包括: IMagic CreateMagic (分别是接口,类)。

     

HG回购代码已更新,如   有下面的PasteBin链接。

详细信息:

有一个包含2个依赖项的类

public SomeClassWithILogDependency(ILog log, ISecond<T> second)

'ILog'有一个为它定义的InjectionModule,就像在文档中那样

LogforIntegration)见帖子底部

如果该类只有1个依赖项,则此行Autofac注册在最简单的场景中起作用:

builder.RegisterType<SomeClassWithILogDependency>()
.As<IUseILog>()
.PropertiesAutowired();

BUT

我需要在注册中调用container.Resolve<ISecond<T>>()以获取有关该类的更多参数,但是这样的事情不起作用:

builder.Register(
    c => new SomeClassWithILogDependency(
        c.Resolve<ILog>(), c.Resolve<ISecond<T>>()))
    .As<IUseILog>()
    .PropertiesAutowired(); //with or without this

c.Resolve<ILog>()“服务尚未注册的问题。”

我也试过

SomeClassWithILogDependency(c.ResolveOptional<ILog>() //without luck...

关于我错过了什么或完全不同的策略的任何想法?我希望解决方案不是有更多的InjectionModules ......

完整代码在PasteBin.com上发布为单个文件

来自bitbucket.org

的整个解决方案

  

hg clone https://NickJosevski@bitbucket.org/NickJosevski/autofaclog4netdemo

注射模块代码(使这篇文章完整):

public class LogInjectionModule : Module
{
    protected override void AttachToComponentRegistration(
        IComponentRegistry registry, IComponentRegistration registration)
    {
        registration.Preparing += OnComponentPreparing;
    }

    private static void OnComponentPreparing(object sender, PreparingEventArgs e)
    {
        var t = e.Component.Activator.LimitType;

        e.Parameters = e.Parameters.Union(new[]
            {
                new ResolvedParameter(
                (p, i) => p.ParameterType == typeof (ILog),
                (p, i) => LogManager.GetLogger(t))
            });
    }
}

1 个答案:

答案 0 :(得分:9)

感谢bentayloruk的建议,解决方案实际上正在使用:

WithParameter(/* ... */)

所以注册码现在看起来像这样:

builder.RegisterType<SomeClassWithILogDependency<IMagic>>()
.As<IUseILog>()
.WithParameter(
    (pi, c) => pi.ParameterType == (typeof(ISecond<>)),
    (pi, c) => c.ResolveNamed<ISecond<IMagic>>("second")
    );
  

示例应用程序已更新,但不是 pastebin条目。

更多信息:

这是我的生产代码的简化示例,比我的实际代码稍微容易解决,其中的解决方案涉及使用具体类型进行ParameterType检查的更具体步骤,例如在这个'do​​main'中

pi.ParameterType == (typeof(CreateMagic))

原因是我的生产 SomeClassWithILogDependency 没有用接口包装其通用参数,但我选择使示例应用程序显示问题的操作略有不同但产生相同的问题。

//demo:
class SomeClassWithILogDependency<TTypeOfISecond> : IUseILog
{
    public SomeClassWithILogDependency(ILog log, ISecond<TTypeOfISecond> second)
}
//-------------- vs --------------
//production:
public class RealClass<TOne, TTwo>, IRealClass<TOne, TTwo>
{
    public RealClass(ILog log, TOne t1, TTwo t2)
}