0

注意:为了澄清,这个问题不是关于在 MVC 控制器中设置 IoC,而是在它们之外。

我的控制器中的 IoC 工作正常,但是我需要让它在自定义类中的控制器之外工作(在使用 CacheBuilders 列表来构建缓存的 CacheManager 类中)。

为此,到目前为止,我将 Windsor 容器的引用传递给 CacheManager,而 CacheManager 会将其传递给每个 CacheBuilder 以解析它可能需要解析的任何引用。但是我认为这不是一个好主意,我想在不传递此参考的情况下这样做,从我读到的内容来看,我认为类型化工厂可以帮助我解决这个问题。

我创建了一个如下所示的界面...

public interface ITypeFactory
{
    T Create<T>();
    void Release(object value);
}

...并将其注册为 BootStrapContainer 方法中的工厂类型,该方法在 Web 应用程序启动时被触发...。

 container.AddFacility<TypedFactoryFacility>();
 container.Register(Component.For<ITypeFactory>().AsFactory());

现在我打算在我的一个 CacheBuilders 中使用它作为以下内容......

public class CountryCacheBuilder : ICacheBuilder
{
    public ITypeFactory TypeFactory { get; set; }

    public void PersistToCache(Cache cache)
    {
        var repository = TypeFactory.Create<ICountryRepository>();

        var listOfCountries = repository.GetAllCountries();

        // add list of Countries to cache
    }
}

...给定 ICountryRepository 定义如下....

public interface ICountryRepository
{
    List<Country> GetAllCountries();
}

...在 Global.asax App_Start 方法中,我像这样向 CacheManager 注册所有 CacheBuilders ...

CacheManager.Instance.CacheBuilders.Add(new CountryCacheBuilder());

然后打电话

CacheManager.BuildCache()

它只是遍历 CacheBuilders 列表并为它们中的每一个触发 PersistToCache。

但是,在 CountryCacheBuilder.PersistToCache 方法中,我看到 TypeFactory 属性在我期望它被实例化时为空。有人能告诉我我在这里想念什么吗?我是否需要告诉容器如何创建每个 CacheBuilder ?

4

1 回答 1

1

我正在将 Windsor 容器的引用传递给 CacheManager ...我相信这不是一个好主意

你说的对; 这不是一个好主意。您基本上是在应用Service Locator 反模式

我创建了一个如下所示的界面...

您只是为您的 IoC 容器创建了一个抽象,它仍然是 Service Locator 反模式的实现。换句话说,仍然是个坏主意。

ITypeFactory您应该简单地注入类所需的依赖项,而不是注入. 此外,您不应该使用属性注入,因为 Castle Windsor 仍会为您创建一个类,即使它的依赖关系无法解决(它只是跳过无法注入的属性)。这听起来不错,但您宁愿希望您的应用程序快速失败,而不是允许容器返回一个无法使用的实例(因为大多数依赖项通常是类工作所必需的)。

CountryCacheBuilder应该是这样的:

public class CountryCacheBuilder : ICacheBuilder
{
    private readonly ICountryRepository repository;

    public CountryCacheBuilder(ICountryRepository repository)
    {
        this.repository = repository;
    }

    public void PersistToCache(Cache cache)
    {
        var listOfCountries = this.repository.GetAllCountries();

        // add list of Countries to cache
    }
}

Castle Windsor(以及与此相关的任何其他 IoC 容器)将分析该类的构造函数并注入其依赖项。您不仅应该为这种类型应用构造函数注入模式,还应该为它的依赖项和消费者应用构造函数注入模式。例如,您的控制器可能如下所示:

public class CountryController : Controller
{
    private readonly ICacheBuilder cacheBuilder;

    public CountryController(ICacheBuilder cacheBuilder)
    {
        this.cacheBuilder = cacheBuilder;
    }

    public ActionResult Index()
    {
        // ...
    }
}

然而,默认情况下,MVC 将为您创建控制器类,而不是 Castle。您必须将创建重定向到 Castle

于 2013-09-16T09:50:45.643 回答