C# 具有Autofac依赖项的工厂
我想写一个工厂来创建各种类型的“xxNotification”类。我的具体“xxNotification”具有已向AutoFac注册的依赖项。我想使用Autofac获取/解析“xxNotification”的实例。怎么做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
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")
});