3

我有一个使用 Castle Windsor 的报告 MVC 应用程序。

在应用程序启动时(在 global.asax 中),所有类型都已注册,然后对应用程序的每个后续请求都会解析相关的报告类型,并且 Windsor 会自动处理依赖关系。

我需要根据请求中传入的参数将其中一种依赖类型切换为另一种。

我怎样才能做到这一点?

我已经向 windsor 注册了一个工厂方法来处理可切换类型的解析,但是由于这是在应用程序启动时注册的,所以当参数仅在以后的请求中可用时,如何将参数传递给工厂方法?

如果我尝试为每个请求注册工厂,它​​会在第一个请求上工作,但随后会抱怨工厂已经注册的所有后续请求。在每次请求后取消注册工厂听起来不像是正确的做法。

4

4 回答 4

2

当你需要在运行时解析类型时,通常的解决方案是注入一个可以在适当的时候做出决定的工厂:

public class ReportFactory: IReportFactory {
    IReport CreateReport(bool useDefault) {
        if (useDefault) {
            return new DefaultReport();
        } else {
            return new UnusualReport();
        }
    }
}

以前需要 an 的类IReport应该需要 an IReportFactory

于 2010-09-22T16:52:24.353 回答
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();
     }
}

然后,您的控制器将获取工厂的实例,并让工厂决定要实例化哪种类型。

于 2010-09-22T16:57:13.953 回答
2

为您的工厂使用TypedFactoryFacility

您可以采取两种方法:

  • 拥有一个具有两种方法的工厂,并利用它用于定位组件的默认约定:

使用默认约定,如果您注册了一个名为“CustomFoo”的组件,则第二种方法将解析该组件,而第一种方法将获得默认值。

public interface IFooFactory
{
   IFoo GetFoo(...arguments);
   IFoo GetCustomFoo(..arguments);

   void ReleaseFoo(IFoo foo);
}
于 2010-09-23T01:10:57.230 回答
1

在 Mike Hadlow 的博客上看到一篇文章,该文章使用在 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");

也许不像注册工厂那么容易理解,但不需要工厂类。

于 2011-01-14T14:57:56.480 回答