这个中央静态类的实现是否正确?

时间:2012-07-06 13:51:01

标签: c# castle-windsor

所以,我正在开始一个新项目,试图实现我在过去几年中学到的一些东西,第一个是使用Castle for 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;
        }

    }

2 个答案:

答案 0 :(得分:4)

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

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

Krzysztof在his NDC presentations

上已经清楚地描述了正确的方法
  • 根据MVC3实施,使用工厂将IoC容器插入应用程序
  • 请尽快解决:针对非网络应用的单个解决方案,针对网络方案的每个请求解决一个问题
  • 一直发布你解决的问题

答案 1 :(得分:0)

您可以通过向“服务定位器”实施迈出一步来清理它。 (事实上​​,a common library就是这样做的。)

例如,您可以在接口后面抽象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容器具有该功能)则需要紧密耦合到该特定容器或扩展此实现以包括以某种方式利用该功能的自定义属性。 p>