我有一个使用Castle Windsor的报告MVC应用程序。
在应用程序启动时(在global.asax中),所有类型都被注册,然后每个后续的应用程序请求都会解析相关的报告类型,windsor会自动处理依赖项。
我需要根据请求中传入的参数切换其中一种依赖类型。
我怎样才能做到这一点?
我已经使用windsor注册了一个工厂方法来处理可切换类型的分辨率但是因为这是在应用程序启动时注册的,当参数仅在以后的请求中可用时,如何将参数传递给工厂方法?
如果我尝试为每个请求注册工厂,它会在第一次请求时工作,但随后会抱怨工厂已经注册的所有后续请求。在每次请求之后取消注册工厂听起来不是正确的事情。
答案 0 :(得分:2)
当您需要在运行时解析类型时,通常的解决方案是注入一个可以在适当的时间做出决定的工厂:
public class ReportFactory: IReportFactory {
IReport CreateReport(bool useDefault) {
if (useDefault) {
return new DefaultReport();
} else {
return new UnusualReport();
}
}
}
之前需要IReport
的类应该要求IReportFactory
。
答案 1 :(得分:2)
您绝对不希望根据请求修改容器。这是灾难的秘诀。
你有两个选择。第一种是在工厂方法中使用HttpContext.Current。
IWhatever CreateWhatever() {
if (HttpContext.Current.Request["parameter"] == "value-for-other-whatever")
return new FirstWhatever();
return DefaultWhatever();
}
另一个(更好的)选项是注入一个解析正确实现的工厂类型,而不是让容器为你做。
public class WhateverFactory : IWhateverFactory {
public IWhatever GetWhatever(string parameter) {
if(parameter == "value for other whatever")
return new OtherWhatever();
return new DefaultWhatever();
}
}
然后您的控制器将获取工厂的实例,并让工厂决定实例化哪种类型。
答案 2 :(得分:2)
将TypedFactoryFacility用于您的工厂。
你可以拿两个appraoches:
使用默认约定,如果您有一个名为“CustomFoo”的组件,第二种方法将解析该组件,而第一种方法将获得默认组件。
public interface IFooFactory
{
IFoo GetFoo(...arguments);
IFoo GetCustomFoo(..arguments);
void ReleaseFoo(IFoo foo);
}
答案 3 :(得分:1)
在Mike Hadlow的博客上遇到article,该博客使用在Windsor注册的代理人返回多个已命名的类型注册中的一个...
所以基本上Windsor注册可能看起来像这样......
container
.Register(
Component.For<IReportFormatter>().ImplementedBy<ReportFormatterWord2003>().Named("word2003"),
Component.For<IReportFormatter>().ImplementedBy<ReportFormatterWord2007>().Named("word2007"),
Component.For<IReportFormatter>().ImplementedBy<ReportFormatterPdf>().Named("pdf"),
Component.For<Func<string, IReportFormatter>>().Instance(container.Resolve<IReportFormatter>),
Component.For<Foo>());
并且Foo构造函数将获取委托类型的参数
Foo(Func<string, IReportFormatter> reportFormatterFactory)
现在当Windsor解析Foo时,reportFormatterFactory没有解析为IReportFormatter的实现,而只是它持有对container.Resolve方法的引用......
container.Resolve<IReportFormatter>(string)
以后可以通过调用...来获取正确的IReportFormatter
reportFormatterFactory("word2007");
或许不像注册工厂那样容易理解,但不需要工厂类。