如何注入与Autofac具有两倍相同接口的构造函数

时间:2018-09-21 20:16:14

标签: c# inversion-of-control autofac constructor-injection

我想用Autofac IoC替换Xamarin 3.2 App中的Unity IoC。因为我没有使用Autofac的经验,并且文档没有解释我的需要,所以希望任何人都可以帮助我。

我不知道,如果该类在构造函数中获得两个相同类型但实现方式不同的接口,则该如何配置构造函数注入。我的示例显示了两个存储库和一个外观。我想为两个存储库(相同的接口类型)提供外观构造器。

我有什么

public class HostManager : IHost
    {
           public HostManager()
           {
           }
    }
    public class CustomerRepository : IRepository
    {
           public CustomerRepository(Context context)
           {
           }
    }
    public class AgentRepository : IRepository
    {
           public AgentRepository(Context context)
           {
           }
    }
    public class ToDoFacade : IFacade
    {
    	public ToDoFacade(IHost host, IRepository agentRepository, IRepository customerRepository)
    	{
    	}
    }

    // IoC registration

    public class Registry
    {
        public Registry()
        {
    	var builder = new ContainerBuilder();
    	builder.RegisterType<HostManager>().As<IHost>().SingleInstance();
    	builder.RegisterType<AgentRepository>().As<IRepository>().PreserveExistingDefaults();
    	builder.RegisterType<CustomerRepository>().Named<IRepository>("Customer");

// How can I continue here?
    	builder.RegisterType<ToDoFacade>().As<IFacade>().UsingConstructor(...);
        }
    }

您对我有一个主意,我该如何解决?也欢迎链接到资源。

最佳蒂诺

3 个答案:

答案 0 :(得分:1)

如果要使用Autofac注入特定的实现,则可以简单地注入类本身,但是您需要通过在注册定义中添加AsSelf使其本身可注入:

builder.RegisterType<AgentRepository>().AsSelf().As<IRepository>();
builder.RegisterType<CustomerRepository>().AsSelf().As<IRepository>().Named<IRepository>("Customer");

然后,您可以直接注入它:

public class ToDoFacade : IFacade
{
    public ToDoFacade(IHost host, AgentRepository agentRepository, CustomerRepository customerRepository)
    {
    }
}

此外,如果您想注入所有IRepository实现,则只需执行以下操作即可:

public ToDoFacade(IHost host, IEnumerable<IRepository> repositories)
{
}

答案 1 :(得分:0)

您可以使用ResolvedParameter向您的班级注入某些已命名的注册。这是一个测试示例:

[Test]
public void InjectCertainRegistration()
{
    // Arrange 
    var registry = new Registry();

    // Act
    var facade = registry.GetFacade();

    // Assert
    Assert.IsInstanceOf<AgentRepository>(facade.AgentRepository);
    Assert.IsInstanceOf<CustomerRepository>(facade.CustomerRepository);
}

// IoC registration
public class Registry
{
    private readonly IContainer _root;

    public Registry()
    {
        var builder = new ContainerBuilder();
        builder.RegisterType<HostManager>().As<IHost>().SingleInstance();
        builder.RegisterType<AgentRepository>().As<IRepository>().Named<IRepository>("Agent").PreserveExistingDefaults();
        builder.RegisterType<CustomerRepository>().Named<IRepository>("Customer");

        builder.RegisterType<ToDoFacade>().As<IFacade>()
            .WithParameter(new ResolvedParameter((p, ctx) => p.Name == "agentRepository",
                (p, ctx) => ctx.ResolveNamed<IRepository>("Agent")))
            .WithParameter(new ResolvedParameter((p, ctx) => p.Name == "customerRepository",
                (p, ctx) => ctx.ResolveNamed<IRepository>("Customer")));

        _root = builder.Build();
    }

    public IFacade GetFacade()
    {
        return _root.Resolve<IFacade>();
    }
}

public class ToDoFacade : IFacade
{
    /// <summary>
    /// Just for testing
    /// </summary>
    public IRepository AgentRepository { get; }

    /// <summary>
    /// Just for testing
    /// </summary>
    public IRepository CustomerRepository { get; }

    public ToDoFacade(IHost host, IRepository agentRepository, IRepository customerRepository)
    {
        AgentRepository = agentRepository;
        CustomerRepository = customerRepository;
    }
}

public class CustomerRepository : IRepository
{
    public CustomerRepository()
    {
    }
}
public class AgentRepository : IRepository
{
    public AgentRepository()
    {
    }
}

public interface IFacade
{
    /// <summary>
    /// Just for testing
    /// </summary>
    IRepository AgentRepository { get; }

    /// <summary>
    /// Just for testing
    /// </summary>
    IRepository CustomerRepository { get; }
}

public class HostManager : IHost
{
    public HostManager()
    {
    }
}

public interface IHost { }

public interface IRepository { }

我已经稍微修改了您的示例。方法Registry.GetFacade()返回 来自容器的IFacade个实例。另外,我还添加了存储库属性以确保它们在测试中的类型。存储库的构造函数变得无参数,只是为了简化示例。希望对您有所帮助。

答案 2 :(得分:0)

如果您已经注册了同一接口的两个实现,则可以向该类中注入IEnumerable<IYourInterface>。如果您需要根据某些条件选择实现,那么autofac documentation会很整洁。