使用温莎城堡子容器解析具有特定实例的类型
我目前正在使用温莎城堡的子容器功能来覆盖工厂方法中特定实例对特定类型的注册。我纯粹使用子容器,以便注册对于单个分辨率来说是临时的 - 换句话说,我不希望注册影响该类型的所有分辨率。
也许一些代码可以解释我的意思。
我有一个充当工厂 Func
的 Func - 我给它一个 IReportCategory 的实现,它返回一个 IReportCategoryViewModel 的新实例。 (IReportCategoryViewModel 依赖于 IReportCategory)。
这是在 Castle Windsor 中注册的,如下所示:
container.Register(
Component.For<Func<IReportCategory, IReportCategoryViewModel>>().Instance(
category => ResolveCategoryViewModelFactory(container, category)));
其中 ResolveCategoryViewModelFactory
的实现如下:
private CategoryViewModel ResolveCategoryViewModelFactory(IWindsorContainer container, IReportCategory category)
{
using (IWindsorContainer childContainer = new WindsorContainer())
{
childContainer.Register(Component.For<IReportCategory>().Instance(category));
container.AddChildContainer(childContainer);
return childContainer.Resolve<IReportCategoryViewModel>();
}
}
上述方法实现的是 IReportCategoryViewModel 的解析,将 IReportCategory 的具体实例作为依赖注入。如果 IReportCategoryViewModel 有其他需要满足的依赖项,那么这些依赖项将由容器自动注入。
我随后可以按如下方式使用 Func:
public class Test
{
private readonly Func<IReportCategory, IReportCategoryViewModel> factory;
public Test(Func<IReportCategory, IReportCategoryViewModel> factory)
{
this.factory = factory;
}
public void ResolveTest()
{
// Create a category (note: this would probably be resolved from the container in some way)
IReportCategory category = new ReportCategory();
// Call into the factory to resolve the view model
IReportCategoryViewModel vm = factory(category);
}
...
问题:这看起来合适吗?根据我的印象,温莎城堡不建议使用子容器 - 是否有其他方法可以达到相同的结果?
感谢您的帮助。
I'm currently using Castle Windsor's child container functionality to override the registration of a particular type with a specific instance in a factory method. I am using the child containers purely so that the registration is temporary for a single resolution - in other words, I don't want the registration to affect all resolutions for that type.
Perhaps some code will explain what I mean.
I have a Func which acts as a factory Func<IReportCategory, IReportCategoryViewModel>
- I give it an implementation of an IReportCategory and it returns a new instance of an IReportCategoryViewModel. (IReportCategoryViewModel has a dependency on IReportCategory).
This is registered with Castle Windsor as follows:
container.Register(
Component.For<Func<IReportCategory, IReportCategoryViewModel>>().Instance(
category => ResolveCategoryViewModelFactory(container, category)));
Where ResolveCategoryViewModelFactory
is implemented as follows:
private CategoryViewModel ResolveCategoryViewModelFactory(IWindsorContainer container, IReportCategory category)
{
using (IWindsorContainer childContainer = new WindsorContainer())
{
childContainer.Register(Component.For<IReportCategory>().Instance(category));
container.AddChildContainer(childContainer);
return childContainer.Resolve<IReportCategoryViewModel>();
}
}
What the above method achieves is the resolution of IReportCategoryViewModel, injecting the specific instance of IReportCategory as a dependency. If IReportCategoryViewModel has other dependencies that need satisfying, then these get automatically injected by the container.
I can subsequently use the Func as follows:
public class Test
{
private readonly Func<IReportCategory, IReportCategoryViewModel> factory;
public Test(Func<IReportCategory, IReportCategoryViewModel> factory)
{
this.factory = factory;
}
public void ResolveTest()
{
// Create a category (note: this would probably be resolved from the container in some way)
IReportCategory category = new ReportCategory();
// Call into the factory to resolve the view model
IReportCategoryViewModel vm = factory(category);
}
...
Question: Does this seem like a suitable thing to do? From the impression I get, child containers are not recommended in Castle Windsor - is there another way of achieving the same result?
Thanks for your help.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
遵循 Krzysztof 使用类型化工厂的建议,以下是我实现上述功能的方法。它比使用子容器简单得多!
首先,创建一个定义工厂方法签名的工厂接口:
接下来,确保在容器中启用
TypedFactoryFacility
:最后,向容器注册工厂接口:
现在您可以注入
ICategoryViewModelFactory
到您的类中,并调用Create()
方法来创建CategoryViewModel
的新实例:警告: 参数名称在工厂方法需要与工厂创建的对象的构造函数的参数名称相匹配。在上面的示例中,工厂接口定义了方法:
CategoryViewModel
的构造函数还必须具有名为“category”的参数:这是因为工厂方法等效于以下内容:
Following Krzysztof's advice to use Typed Factories, here is how I implemented the above functionality. It is far more simpler than using child containers!
Firstly, create a factory interface which defines the signature of the factory method:
Next, ensure the
TypedFactoryFacility
is enabled in the container:Finally, register the factory interface with the container:
Now you can inject
ICategoryViewModelFactory
into your classes, and call theCreate()
method to create a new instance ofCategoryViewModel
:Warning: The parameter name in the factory method needs to match the parameter name of the constructor of the object the factory creates. In the above example, the factory interface defines the method:
The constructor for
CategoryViewModel
must also have the parameter named "category":This is because the factory method is the equivalent of the following:
绝对有更好的方法可以走,并且您现在使用的代码有一个错误 - 当您处置子容器时,它将尝试释放您正在解析的所有组件实例,因此它们可能无法使用(处置)在你有机会使用它们之前。
如果我正确理解你的解释,感觉就像是类型化工厂的工作。
Absolutely there are better ways to go, and the code you're using right now has a bug - it will try to release all the component instances you're resolving when you dispose of the child container, therefore they might be unusable (disposed) before you even get a chance to use them.
If I understand your explanation correctly it feels like a job for typed factories.