如何使用Autofac将参数传递给构造函数

时间:2014-11-28 04:49:40

标签: c# dependency-injection autofac

我确定我在这里错过了一些东西。

我正在尝试将非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));

3 个答案:

答案 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参数并使用工厂用适当的内部设置实例化我的对象。对我来说效果很好,但我确信策略模式也是有效的。