Autofac依赖注入 - 根据程序集解析为不同类型

时间:2017-05-18 07:46:57

标签: c# dependency-injection autofac

我正在构建一个c#Asp.Net应用程序。 我的项目中有三个程序集。

  • MainAssembly
  • AssemblyA
  • AssemblyB

AssemblyAAssemblyB引用了MainAssembly。 MainAssembly将使用Reflection加载AssemblyAAssemblyB。 需要AutoFac来根据它所在的程序集来解析类型。

换句话说,构造函数参数应根据它所属的程序集解析为SmsSenderEmailSender

请考虑以下代码:

-------------------------- MainAssembly内的代码 ----------- ---------------

//Global Registration
void AutofacRegister()
{
   var builder = new ContainerBuilder();
   ...
   ...
   //Registering the modules in other assemblies
   builder.RegisterAssemblyModules(AssemblyA);
   builder.RegisterAssemblyModules(AssemblyB);
   ...

}

interface ISender
{
  void SendMessage();
}

-------------------------- AssemblyB内的代码 ----------- -----------------

public class ComponentA: Module
{
   protected override void Load(ContainerBuilder builder)
   {
       builder.RegisterType<SmsSender>().As<ISender>();
   }
}

internal class SmsSender : ISender{...}

public class Foo()
{
   Foo(ISender sender)
   {
      //as this is inside a AssemblyA thi should be resolved to type SmsSender
      //SmsSender
   }
}

-------------------------- AssemblyB内的代码 ----------- -----------------

public class ComponentA: Module
{
   protected override void Load(ContainerBuilder builder)
   {
       builder.RegisterType<EmailSender>().As<ISender>();
   }
}

internal class EmailSender : ISender{...}

public class Bar()
{
   Bar(ISender sender)
   {
      //as this is inside a AssemblyB this should be resolved to type EmailSender
      //EmailSender
   }
}

我如何达到要求? 可以通过提供一个简单的例子来帮助我吗?

1 个答案:

答案 0 :(得分:0)

有多种方法可以解决您的问题,但您必须明确“告诉”您FooBar他们应该使用的ISender类。您可以使用“命名实例”来执行此操作。

首先,我假设MainAssembly中不存在ISender接口,因为如果MainAssembly引用了这两个组件,它在ComponentA和ComponentB中是不可访问的。

您的 ComponentA 模块定义应如下所示:

public class ModuleDefinition : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        const string emailSender = "EmailSender";

        builder.RegisterType<EmailSender>().As<ISender>().Named<ISender>(emailSender);
        builder.RegisterType<Foo>()
            .WithParameter((p, c) => p.Name == "sender", (p, c) => c.ResolveNamed<ISender>(emailSender));
    }
}

类似地, ComponentB 模块定义如下所示:

public class ModuleDefinition : Module
{
    protected override void Load(ContainerBuilder builder)
    {
        const string smsSender = "SmsSender";

        builder.RegisterType<SmsSender>().As<ISender>().Named<ISender>(smsSender);
        builder.RegisterType<Bar>()
            .WithParameter((p, c) => p.Name == "sender", (p, c) => c.ResolveNamed<ISender>(smsSender));
    }
}

如您所见,我使用ISender配置方法明确配置FooBar类应使用哪个.WithParameter实现。

AFAIK没有隐含的“基于程序集”的方式。