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

Nic*_*ski 5 .net registration autofac

摘要:

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

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

使用RegisterType <>而不是Register()并没有解决我在生产代码中的实际复杂程度,我已经更新了BitBucket上的演示代码以包含一个通用的 ISecond,其示例包括:IMagicCreateMagic(接口,类)分别).

HG repo代码已更新,下面的PasteBin链接也已更新.

细节:

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

public SomeClassWithILogDependency(ILog log, ISecond<T> second)
Run Code Online (Sandbox Code Playgroud)

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

(LogforIntegration)见帖子的底部

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

builder.RegisterType<SomeClassWithILogDependency>()
.As<IUseILog>()
.PropertiesAutowired();
Run Code Online (Sandbox Code Playgroud)

我需要container.Resolve<ISecond<T>>()在注册时调用类中的更多参数,但是这样的东西不起作用:

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

c.Resolve<ILog>()是问题"该服务尚未注册."

我也试过了

SomeClassWithILogDependency(c.ResolveOptional<ILog>() //without luck...
Run Code Online (Sandbox Code Playgroud)

关于我错过了什么或完全不同的策略的任何想法?我希望解决方案不是有更多的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))
            });
    }
}
Run Code Online (Sandbox Code Playgroud)

Nic*_*ski 9

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

WithParameter(/* ... */)
Run Code Online (Sandbox Code Playgroud)

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

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

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

更多信息:

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

pi.ParameterType == (typeof(CreateMagic))
Run Code Online (Sandbox Code Playgroud)

原因是我的生产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)
}
Run Code Online (Sandbox Code Playgroud)