代码之家  ›  专栏  ›  技术社区  ›  vpetrovic

具有Autofac依赖项的工厂

  •  3
  • vpetrovic  · 技术社区  · 7 年前

    我想写一个工厂来创建各种类型的“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
            }
        }
    }
    
    1 回复  |  直到 7 年前
        1
  •  2
  •   NightOwl888 Jabrwoky    7 年前

    这看起来是一个很好的候选人 Strategy Pattern

    接口

    public interface INotification
    {
        void Notify(string Action, int OrderID);
        bool AppliesTo(string NotificationName);
    }
    
    public interface INotificationStrategy
    {
        void Notify(string NotificationName, string Action, int OrderID);
    }
    

    INotification实现

    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);
        }
    }
    

    注意,另一种方法是使用基于OrderID的一些“OrderType”状态来查找要使用的服务(不确定将OrderID传递到Notify()方法中是否有意义)。但不管你如何划分,这是一个应用程序设计问题,而不是DI问题。

    Autofac注册

    a few ways 您可以将Autofac配置为注册同一接口的多个实现,以便在中使用 NotificationStrategy

    扫描

    // 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();
    

    当以这种方式注册实现时,Autofac将隐式地将所有实现注入任何 IEnumerable<INotification>

    樱桃采摘

    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")
                        });