我想在Autofac中实现工厂模式。这是在Ninject中完成的:
Bind<ICarFilter>().To<CarFilter >();
Bind<IBikeFilter>().To<BikeFilter>();
Bind<IFilterFacade>().ToFactory().InSingletonScope();
这是IFilterFacade的定义
public interface IFilterFacade
{
ICarFilter CreateCarFilter();
IBikeFIlter CreateBikeFilter();
}
如果我想要一个CarFilter类型的实例,我需要做的就是:
public class HomeController(IFilterFacade filterFacade)
{
FilterFacade = filterFacade;
}
public IFilterFacade FilterFacade { get;set; }
public ActionResult Index()
{
var bikeFilter = FilterFacade.CreateBikeFilter();
}
如何在AutoFac中执行此操作的任何示例。我检查了AutoFac文档,但无法找到答案或示例。
答案 0 :(得分:1)
Autofac 中没有等效的ToFactory
,但您可以轻松实现等效的通用工厂。
public interface IFilterFactory
{
TFilter Get() where TFilter : IFilter;
}
public class FilterFactory : IFilterFactory
{
public FilterFactory(ILifetimeScope scope)
{
this._scope = scope;
}
private readonly ILifetimeScope _scope;
public TFilter Get<TFilter>()
{
return this._scope.Resolve<TFilter>();
}
}
然后像这样注册:
builder.RegisterType<FilterFactory>().As<IFilterFactory>();
builder.RegisterType<BikeFilter>().As<IBikeFilter>();
builder.RegisterType<CarFilter>().As<ICarFilter>();
并以这种方式使用
public class HomeController
{
private readonly IFilterFactory _filters;
public HomeController(IFilterFactory filters)
{
this._filters = filters;
}
public ActionResult Index()
{
var bikeFilter = this._filters.Get<IBikeFilter>();
// ...
}
}
我将Create
方法重命名为Get
,因为该方法将在生命周期范围内查找实例,并仅在需要时创建一个实例。
另一种可能的解决方案可能是使用Named and Keyed Service和内置IIndex
类型。
builder.RegisterType<BikeFilter>().Named<IFilter>("Bike");
builder.RegisterType<CarFilter>().Named<IFilter>("Car");
然后在您的控制器上
public class HomeController
{
private readonly IIndex<String, IFilter> _filters;
public HomeController(IIndex<String, IFilter> filters)
{
this._filters = filters;
}
public ActionResult Index()
{
var bikeFilter = this._filters["Bike"];
// ...
}
}
答案 1 :(得分:0)
Autofac没有动态实现用户定义的工厂界面的功能。它确实允许绑定代表,但它不一样。
如果你想在构造函数中接收一种工厂,那么用相关的方法从那个工厂获得单个组件,这绝对可以用Autofac。
撰写根
在这里,我将单个组件注册为单例(这是Ninject的行为,如果我能正确理解),但您可以使用任何符合您要求的生命周期选项。
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<BikeFilter>().As<IBikeFilter>().SingleInstance();
builder.RegisterType<CarFilter>().As<ICarFilter>().SingleInstance();
<强>控制器强>
public class HomeController
{
private readonly IComponentContext _components;
public HomeController(IComponentContext components)
{
_components = components; // instead of factory interface
}
public ActionResult Index()
{
var bikeFilter = _components.Resolve<IBikeFilter>();
// ...
}
}
BTW
我认为工厂界面是Ninject的一个很好的功能。它的另一个附加价值是允许通过IntelliSense进行探索。在您的示例中,当我键入FilterFacade
和点字符时,我会看到支持的过滤器列表(CreateCarFilter,CreateBikeFilter,...)。即使我不完全熟悉项目代码库,我也可以选择一个最合适的代码库。使用Autofac,IComponentContext
允许我请求任何组件,这不会帮助我找出存在哪些相关组件,或者我希望请求哪些组件。
答案 2 :(得分:0)
我写了一个NuGet来做到这一点,但是在IServiceCollection
上。