带有配置文件和单例类的Unity框架

时间:2009-12-10 21:32:10

标签: singleton unity-container ioc-container

故事就是这样:

我有单例类(a.k.a ServiceLocator),您可以使用“CreateInstance()”方法获取实例。同时,我们将Unity添加到我们的应用程序中,并使用标准配置文件对其进行配置。

当我尝试映射接口IServiceLocator以获取ServiceLocator的实例并将其注册到unity配置文件中时,问题就开始了。正如您可能猜到的那样,ServiceLocator没有公共构造函数(即singleton),因此,当我执行unity.resolve<IServiceLocator>()时,unity不能创建它....

我的问题:有没有办法告诉Unity(通过配置文件)使用CreateInstance()而不是尝试执行默认构造函数?如果没有,如果您还有其他想法可以做什么,我将不胜感激。

请不要建议我将构造函数更改为public,假设我暂时不能这样做。

1 个答案:

答案 0 :(得分:0)

您最好手动创建UnityContainer并将其注入服务定位器:

public class ServiceLocator 
{
    public static void SetServiceLocatorProvider(IServiceLocator serviceLocator)
    {
        Instance = serviceLocator;
    }

    public static void SetServiceLocatorProvider(Func<IServiceLocator> serviceLocator)
    {
        Instance = serviceLocator();
    }

    public static IServiceLocator Instance { get; private set; }
}


public class ServiceLocatorContainer : IServiceLocator
{
    private readonly IUnityContainer _unityContainer;

    public ServiceLocatorContainer(IUnityContainer unityContainer)
    {
        _unityContainer = unityContainer;
    }
//skipped for simplicity sake
 }


    public abstract class ApplicationControllerBase  
    {


        /// <summary>
        /// Создать экземпляр Unity контейнера
        /// </summary>        
        private IUnityContainer CreateContainer()
        {
            return new UnityContainer();
        }

        protected virtual void ConfigureContainer()
        {

            RegisterTypeIfMissing(typeof(IServiceLocator), typeof(ServiceLocatorContainer), true);
            RegisterTypeIfMissing(typeof(ISharedAssemblyInitializer), typeof(SharedAssemblyInitializer), true);

            ServiceLocator.SetServiceLocatorProvider(() => this.Container.Resolve<IServiceLocator>());

        }


    protected void RegisterTypeIfMissing(Type fromType, Type toType, bool registerAsSingleton)
    {

        if (Container.IsTypeRegistered(fromType))
        {

        }
        else
        {
            if (registerAsSingleton)
            {
                Container.RegisterType(fromType, toType, new ContainerControlledLifetimeManager());
            }
            else
            {
                Container.RegisterType(fromType, toType);
            }
        }
    }


        public virtual void Run()
        {
            this.Container = CreateContainer();
            this.ConfigureContainer();
        }

        public IUnityContainer Container { get; private set; }
}

这是棱镜扩展到统一的简化版本。在棱镜中查看modulesmanager类的更详细的来源。 应用程序以Run方法启动。您创建容器并在其中注册您的servicelocator。 Wile注册,UnityContainer创建它的实例并将自己传递给ctor:

public ServiceLocatorContainer(IUnityContainer unityContainer)
{
    _unityContainer = unityContainer;
}

然后,使用SetServiceLocatorProvider方法分配给servicelocator类的Instance属性实例,该实例引用了unity容器。这种解决方案还提供了具体DI容器的抽象。您可以从代码中的任何位置引用您的服务定位器。 1)注入构造函数

public class RLoginABS
{

    IServiceLocator serviceLocator;

    public RLoginABS(IServiceLocator serviceLocator)
    {
        this.serviceLocator = serviceLocator;
    }

    public void Login(string user, string password)
    {            
        REnvironmentRWS environment = REnvironmentRWS.Current;            
        serviceLocator.RegisterInstance<IEnvironmentRWS>(environment as IEnvironmentRWS);
    }

}

或使用静态类:

shellViewModel = ServiceLocator.Instance.Resolve<IShellViewModel>();

ps:IServiceLocator接口,它是DI容器的具体实现的抽象:

public interface IServiceLocator
{
    void Register<TInterface, TImplementor>() where TImplementor : TInterface;
    void Register(Type TInterface, Type TImplementor);
    void RegisterAsSingleton<TInterface, TImplementor>() where TImplementor : TInterface;
    T Resolve<T>();
}

它的方法包装了具体容器的方法,例如:

public void Register(Type TInterface, Type TImplementor)
{
    _unityContainer.RegisterType(TInterface, TImplementor);
}

希望 - 它有所帮助!