0

所以,我开始了一个新项目,尝试实现我在过去几年中学到的一些东西,其中第一个是将 Castle 用于 IoC。

我想要一个中央“核心”课程,它将在众多最终项目(控制台应用程序、网站)中共享。所以我想,这里有两个问题:

a)这种方法是否正确 b)我的实施是否正确。

我知道这是一个非常小的课程,但我想从一开始就正确。

public static class Global {
        static IWindsorContainer _Container;
        static int ContainerInitalised = 0;
        static string ServicesFile;

        public static IWindsorContainer Container{
            get{
                if (Interlocked.CompareExchange(ref ContainerInitalised, 1, 0) == 0) {
                    Collection<IWindsorInstaller> installers = new Collection<IWindsorInstaller> {
                        { FromAssembly.InDirectory(new AssemblyFilter("Installers")) }
                    };
                    if (!String.IsNullOrWhiteSpace(ServicesFile)) {
                        installers.Add(Configuration.FromXmlFile(ServicesFile));
                    }
                    _Container = new WindsorContainer().Install(installers.ToArray());
                }
                return _Container;
            }
        }

        public static void Initialise(string servicesFile) {
            ServicesFile = servicesFile;
        }

    }
4

2 回答 2

4

按照 David 的说法,您的想法是使用 ServiceLocator 解决方案,这是使用 IoC 容器的最糟糕的方式。

使用通用接口抽象 IoC 容器也是一个坏主意,因为您最终会失去特殊的容器功能:特别是不公开发布方法的接口会导致使用成熟的 IoC 容器(例如基于 RRR 模式的 Windosr)的灾难。

Krzysztof 在他的 NDC 演讲中清楚地描述了正确的方法

  • 根据 MVC3 实现,使用工厂将 IoC 容器插入您的应用程序
  • 尽快做一个 Resolve:非 web 应用的一个 Resolve,一个 web 场景的每个请求一个 resolve
  • 总是发布你解决的问题
于 2012-07-06T17:12:34.477 回答
0

您可能可以通过向“服务定位器”实现迈出一步来清理它。(确实,有一个通用库可以做到这一点。)

例如,您可以在接口后面抽象 IoC 容器,并拥有一个提供当前实现的静态工厂(以替换您的泛型Global类并使其更具针对性)。像这样的东西:

public interface IoCContainer
{
    object GetInstance(Type serviceType);
    object GetInstance(Type serviceType, string key);
    IEnumerable<object> GetAllInstances(Type serviceType);
    T GetInstance<T>();
    T GetInstance<T>(string key);
    IEnumerable<T> GetAllInstances<T>();
}

public static class IoCContainerFactory
{
    private static IoCContainer current;

    public static IoCContainer Current
    {
        get
        {
            if (current == null)
                throw new DomainException("IoC Container Not Initialized.  This application must call a bootstrap method in an IoC implementation project.");
            return current;
        }
    }

    public static void Initialize(IoCContainer container)
    {
        current = container;
    }
}

然后在另一个项目中我实现了IoCContainer接口(我使用 StructureMap,你使用 Castle……有很多选择)。同样在另一个项目中,我有一个Initializer类将引导容器实现(因为任何实现的配置都不同),并且作为最后一步,初始化这个“全局”工厂:

IoCContainerFactory.Initialize(new IoCContainerImplementation(ObjectFactory.Container));

(在上述代码行的情况下,IoCContainerImplementation是我对上述接口的实现,并且ObjectFactory来自 StructureMap,并且刚刚在之前的代码行中配置/引导。)

当然,使用这种方法,需要进行一些权衡。通过将我的 IoC 容器抽象到一个通用接口后面,我只能做许多 IoC 容器实现中通用的事情。对于我的需要,我想要的只是调用一个方法来解决依赖关系。但是其他的东西,比如用属性装饰类/属性(如果你选择的 IoC 容器具有该功能)将需要与该特定容器紧密耦合或扩展此实现以包含以某种方式使用该功能的自定义属性。

于 2012-07-06T14:02:26.087 回答