2009-12-10 10 views
2

Ainsi, l'histoire va comme ceci:cadre fédérateur avec le fichier de configuration et les classes singleton

Je classe singleton (a.k.a ServiceLocator) que vous pouvez obtenir l'instance en utilisant la méthode « CreateInstance() ». Dans le même temps, nous avons ajouté Unity dans notre application et l'avons configuré en utilisant le fichier de configuration standard.

Le problème a commencé lorsque j'ai essayé de mapper l'interface IServiceLocator pour obtenir l'instance de ServiceLocator et l'enregistrer dans le fichier de configuration d'unité. Comme vous devine probablement, ServiceLocator ne possède pas de constructeur public (c.-à-singleton), par conséquent, l'unité ne peut pas créer quand je fais unity.resolve<IServiceLocator>() ....

Ma question: Est-il possible de dire l'unité (par le fichier de configuration) à utiliser CreateInstance() au lieu d'essayer d'exécuter le constructeur par défaut? Sinon, si vous avez une autre idée de ce qui peut être fait d'autre, je vous serais reconnaissant de l'entendre.

S'il vous plaît ne me propose pas de changer le constructeur au public suppose que je ne peux pas le faire pour l'instant.

Répondre

0

Vous feriez mieux de créer manuellement UnityContainer et l'injecter dans votre localisateur de services:

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; } 
} 

ceci est une version simplifiée de l'extension prisme à l'unité. voir des sources plus détaillées de la classe modulesmanager dans le prisme. application commence par la méthode Run. Vous créez un conteneur et enregistrez votre servicelocator dans celui-ci. Wile enregistrement, UnityContainer crée par exemple de celui-ci et se passer dans cteur:

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

puis, en utilisant la méthode SetServiceLocatorProvider vous attribuez à l'instance de propriété instance de classe ServiceLocator, qui a référence au contenant de l'unité au sein. Une telle solution donne également l'abstraction du conteneur DI concret. Et vous pouvez faire référence à votre localisateur de service à partir de n'importe où dans votre code. 1) Injectiong en constructeur

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); 
    } 

} 

ou en utilisant la classe statique:

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

ps: Interface IServiceLocator, qui est une abstraction de la mise en œuvre concrète du conteneur 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>(); 
} 

ses méthodes enveloppements méthodes de conteneurs en béton, par exemple:

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

Espoir - ça aide!