我想用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(...);
}
}
您对我有一个主意,我该如何解决?也欢迎链接到资源。
最佳蒂诺
答案 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会很整洁。