注意:为了澄清,这个问题不是关于在MVC控制器中设置IoC而是在它们之外。
我的IoC在我的控制器中正常工作但是我需要让它在自定义类中的控制器之外工作(在CacheManager类中使用CacheBuilders列表来构建缓存)。
为此,我将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方法中,我将所有CacheBuilders注册到CacheManager,就像这样......
CacheManager.Instance.CacheBuilders.Add(new CountryCacheBuilder());
然后致电
CacheManager.BuildCache()
只是迭代CacheBuilders列表并为每个人激活PersistToCache。
但是在CountryCacheBuilder.PersistToCache方法中,当我期望它被实例化时,我看到TypeFactory属性为null。谁能告诉我在这里我错过了什么?我是否需要告诉容器如何创建每个CacheBuilder?
答案 0 :(得分:1)
你是对的;这不是一个好主意。您基本上应用了Service Locator anti-pattern。我正在将Windsor容器的引用传递给CacheManager ......我相信这不是一个好主意
我创建了一个如下所示的界面......
您只是为您的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。您必须redirect the creation to Castle。