我确定我在这里错过了一些东西。
我正在尝试将非DI代码转换为使用autofac。我有一个与硬件通信的类,它接受IP地址并抽象出接口。我有一个配置和操作硬件的高级课程。我试图找出如何在不传递DI容器副本的情况下实例化此类的多个副本。
string FirstIP, SecondIP;
//Set values from config/user etc.
var FirstDevice = new HighLevelIF(new LowLevelIF(FirstIP));
var SecondDevice = new HighLevelIF(new LowLevelIF(SecondIP));
如果我只想要一个设备对象,那么在Autofac中连接它似乎很简单。但是要有两个具有不同地址的实例,我只能在运行时知道,我无法通过autofac看到这样做的方法。我能看到的唯一方法是编写一个LowLevelIF工厂,我将其传递给该方法,然后我实例化
var FirstDevice = new HighLevelIFFactory.Create
(LowLevelIFFactory.Create
(FirstIP));
答案 0 :(得分:1)
如果您需要按需解析这些IP并且它们可能会在运行时更改,abstract factory是您最好的选择。
如果您有一个在应用程序启动时加载的地址集,并且您只需要以最有效的方式在这些实例之间切换,则可以使用strategy pattern,这样可以避免注入容器进入你的班级。
策略示例
var builder = new ContainerBuilder();
// Register all instances of IDiscountCalculator
builder.RegisterAssemblyTypes(this.GetType().Assembly)
.Where(t => typeof(IDiscountCalculator).IsAssignableFrom(t));
builder.Register<DiscountStrategy>().As<IDiscountStrategy>();
var container = builder.Build();
var strategy = container.Resolve<IDiscountStrategy>();
Console.WriteLine(strategy.GetDiscount("Regular", 10)); // 0
Console.WriteLine(strategy.GetDiscount("Normal", 10)); // 1
Console.WriteLine(strategy.GetDiscount("Special", 10)); // 5
取决于以下类型:
public interface IDiscountStrategy
{
decimal GetDiscount(string userType, decimal orderTotal);
}
public class DiscountStrategy : IDiscountStrategy
{
private readonly IEnumerable<IDiscountCalculator> _discountCalculators;
public DiscountStrategy(IEnumerable<IDiscountCalculator> discountCalculators)
{
_discountCalculators = discountCalculators;
}
public decimal GetDiscount(string userType, decimal orderTotal)
{
var calculator = _discountCalculators.FirstOrDefault(x => x.AppliesTo(userType));
if (calculator == null) return 0;
return calculator.CalculateDiscount(orderTotal);
}
}
public interface IDiscountCalculator
{
bool AppliesTo(string userType);
decimal CalculateDiscount(decimal orderTotal);
}
public class NormalUserDiscountCalculator : IDiscountCalculator
{
public bool AppliesTo(string userType)
{
return userType == "Normal";
}
public decimal CalculateDiscount(decimal orderTotal)
{
return orderTotal * 0.1m;
}
}
public class SpecialUserDiscountCalculator : IDiscountCalculator
{
public bool AppliesTo(string userType)
{
return userType == "Special";
}
public decimal CalculateDiscount(decimal orderTotal)
{
return orderTotal * 0.5m;
}
}
请注意,使用AppliesTo
方法也意味着您可以制定一个策略,选择适用于特定目的的多个实例,就像过滤器一样。
答案 1 :(得分:0)
您可以使用.WithParameter()
方法。
例如:
var builder = new ContainerBuilder();
builder.RegisterType<MyType>().As<IMyInterface>().WithParameter("paramName", "paramValue");
编辑:重新阅读您的问题。您可能想要为您的注册命名,然后获得适当的注册?
你也可以这样做:
var builder = new ContainerBuilder();
builder.RegisterType<MyType>().Named<IMyInterface>("MyName");
builder.RegisterType<MyType>().Named<IMyInterface>("MyOtherName");
var container = builder.Build();
// later
container.ResolveNamed<IMyInterface>("MyName"); //gets MyName registration
答案 2 :(得分:0)
仅供参考,我创建了工厂方法,将它们传递给构造函数(autofac将自动为您连线)。
然后我有了一个“初始化”方法,它采用了相机IP参数并使用工厂用适当的内部设置实例化我的对象。对我来说效果很好,但我确信策略模式也是有效的。