C# 具有Autofac依赖项的工厂

C# 具有Autofac依赖项的工厂,c#,dependency-injection,autofac,factory-pattern,C#,Dependency Injection,Autofac,Factory Pattern,我想写一个工厂来创建各种类型的“xxNotification”类。我的具体“xxNotification”具有已向AutoFac注册的依赖项。我想使用Autofac获取/解析“xxNotification”的实例。怎么做 public interface INotification { void Notify(string Action, int OrderID); } public class MagentoOrderStateNotification : INotification

我想写一个工厂来创建各种类型的“xxNotification”类。我的具体“xxNotification”具有已向AutoFac注册的依赖项。我想使用Autofac获取/解析“xxNotification”的实例。怎么做

public interface INotification
{
    void Notify(string Action, int OrderID);
}

public class MagentoOrderStateNotification : INotification
{
    private readonly GenericRepository<Order> _orderRepository;
    private readonly OMRestIntegrationService _oMRestIntegrationService;

    public MagentoOrderStateNotification(GenericRepository<Order> orderRepository, OMRestIntegrationService oMRestIntegrationService)
    {
        _orderRepository = orderRepository;
        _oMRestIntegrationService = oMRestIntegrationService;
    }

    public void Notify(string Action, int OrderID)
    {
        //implementation...
    }
}

public class NotificationFactory
{
    public INotification GetNotification(string NotificationName)
    {
        switch (NotificationName)
        {
            case "MagentoOrderStateNotification":
                //resolve instance of MagentoOrderStateNotification
        }
    }
}
公共接口INotification
{
void Notify(字符串操作,int OrderID);
}
公共类MagentoOrderStateNotification:INotification
{
专用只读一般存储库(orderRepository);;
私有只读OMRestIntegrationService\u OMRestIntegrationService;
公共MagentoOrderStateNotification(GenericRepository orderRepository,OMRestIntegrationService OMRestIntegrationService)
{
_orderRepository=orderRepository;
_oMRestIntegrationService=oMRestIntegrationService;
}
public void Notify(字符串操作,int OrderID)
{
//实施。。。
}
}
公共类通知工厂
{
public INotification GetNotification(字符串NotificationName)
{
开关(NotificationName)
{
案例“MagentoOrderStateNotification”:
//解析MagentoOrderStateNotification的实例
}
}
}

这看起来是一个很好的选择

接口 INotification实现 请注意,另一种方法可能是使用基于OrderID的某些“OrderType”状态来查找要使用的服务(不确定将OrderID传递到Notify()方法是否有意义)。但无论您如何划分,这都是一个应用程序设计问题,而不是DI问题

自动传真注册 您可以将Autofac配置为注册同一接口的多个实现,以便在
NotificationStrategy
构造函数中使用。以下是几个例子:

扫描 以这种方式注册实现时,Autofac将隐式地将所有实现注入任何
IEnumerable
构造函数参数

樱桃采摘
builder.Register()
.命名为(“magentoOrderStateNotification”);
builder.Register()
.命名为(“fooOrderStateNotification”);
builder.RegisterType()
.As()
.带参数(
(p,c)=>p.Name==“oNotifications”,
(p,c)=>新[]
{
c、 ResolveNamed(“magentoOrderStateNotification”),
c、 ResolveNamed(“fooOrderStateNotification”)
});

通常,您不会从DI容器“获取”对象。这就是所谓的服务定位器的反模式。相反,应用程序是在启动时编写的,包括工厂及其依赖项。它被称为.OK,那么如果我需要在运行时根据一些配置实例化一个服务,比如“对于这个顺序状态,调用那个和那个INotification”?您可以通过一个方法参数将运行时顺序状态传递到您的服务中。在您的服务中,您可以使用、或选择要使用的一个或多个服务。您也可以根据场景进行选择。NotificationStrategy如何将INotification[]oNotifications作为构造函数参数?我更新了答案。请注意,要使扫描在Autofac中工作,
NotificationStrategy
构造函数需要更改为
IEnumerable
,而不是
INotification[]
。如果我只希望根据某个运行时条件注册一个策略实现,该怎么办,例如指定给CliFx之类的CLI框架的子命令?从组合根目录中不容易知道应该使用哪个具体实现created@void.pointer-这就是
AppliesTo
方法的用途。在启动时注册所有策略实例,然后将筛选逻辑放入
AppliesTo
方法中,选择一个或多个实例在运行时使用。由于总是加载所有实例,因此通常最好将对象数限制在几百个,之后最好使用抽象工厂。因此,在我的例子中,基本上您认为像
builder.Register(c=>c.Resolve().First(cmd=>cmd.IsActive)).As()这样的操作不会滥用?然后在构造函数中,我可以执行
公共MyObject(ICommand cmd)
并在命令行获取用户选择的命令?到目前为止,我一直在使用一个
IActiveCommandProvider
,但你的想法更简洁。
public interface INotification
{
    void Notify(string Action, int OrderID);
    bool AppliesTo(string NotificationName);
}

public interface INotificationStrategy
{
    void Notify(string NotificationName, string Action, int OrderID);
}
public class MagentoOrderStateNotification : INotification
{
    private readonly GenericRepository<Order> _orderRepository;
    private readonly OMRestIntegrationService _oMRestIntegrationService;

    public MagentoOrderStateNotification(GenericRepository<Order> orderRepository, OMRestIntegrationService oMRestIntegrationService)
    {
        _orderRepository = orderRepository;
        _oMRestIntegrationService = oMRestIntegrationService;
    }

    public void Notify(string Action, int OrderID)
    {
        //implementation...
    }

    public bool AppliesTo(string NotificationName)
    {
        // Note that you can make the criteria to use this
        // service as advanced as you need to. You could even
        // design your strategy to use multiple services in specific
        // scenarios. But putting that logic here has many advantages
        // over a switch case statement.
        return NotificationName == "a";
    }
}

public class FooOrderStateNotification : INotification
{
    public void Notify(string Action, int OrderID)
    {
        //implementation...
    }

    public bool AppliesTo(string NotificationName)
    {
        return NotificationName == "b";
    }
}
public class NotificationStrategy : INotificationStrategy
{
    private readonly IEnumerable<INotification> oNotifications;

    public MessageStrategy(IEnumerable<INotification> oNotifications)
    {
        if (oNotifications == null)
            throw new ArgumentNullException("oNotifications");
        this.oNotifications = oNotifications;
    }

    public void Notify(string NotificationName, string Action, int OrderID)
    {
        var notification = this.oNotifications
            .FirstOrDefault(x => x.AppliesTo(NotificationName));

        // Possible alternative: get multiple implementations and
        // then loop through them, executing each one.
        // var notifications = this.oNotifications
        //     .Where(x => x.AppliesTo(NotificationName)).ToArray();

        if (notification == null)
        {
            throw new Exception("No notification type registered for " + NotificationName);
        }

        notification.Notify(Action, OrderID);
    }
}
public class SomeService : ISomeService
{
    private readonly INotificationStrategy oNotificationStrategy;

    public SomeService(INotificationStrategy oNotificationStrategy)
    {
        if (oNotificationStrategy == null)
            throw new ArgumentNullException("oNotificationStrategy");
        this.oNotificationStrategy = oNotificationStrategy;
    }

    public void DoSomething()
    {
        this.oNotificationStrategy.Notify("a", "Hello", 1234);
    }
}
// Note you may need more than one registration if you are spanning
// multiple assemblies.
builder.RegisterAssemblyTypes(typeof(INotification).Assembly)
   .Where(x => typeof(INotification).IsAssignableFrom(x))
   .AsImplementedInterfaces();
builder.Register<MagentoOrderStateNotification>()
    .Named<INotification>("magentoOrderStateNotification");
builder.Register<FooOrderStateNotification>()
    .Named<INotification>("fooOrderStateNotification");

builder.RegisterType<NotificationStrategy>()
            .As<INotificationStrategy>()
            .WithParameter(
                (p, c) => p.Name == "oNotifications",
                (p, c) => new[]
                    {
                        c.ResolveNamed<INotification>("magentoOrderStateNotification"),
                        c.ResolveNamed<INotification>("fooOrderStateNotification")
                    });