2013-05-30 2 views
14

Sono nuovo a Unity e sto provando a scrivere una logica Unity che inizializza e registra/risolve un'istanza singleton dell'oggetto Email in modo che possa essere utilizzata su molti altri oggetti, un esempio sotto è OperationEntity.Unity Singleton Code

Così quando è registrato popola il singleton Email con alcuni valori da un file di configurazione, quindi ogni volta che viene creata un'istanza di OperationEntity (nel mio caso viene deserializzata) utilizza lo stesso singleton Email. Quindi tutta la logica del mio client deve essere deserializzare OperationEntity e chiamare PerformAction() - con l'istanza dell'email gestita da Unity.

public interface IEmail 
{ 
    string FromName { get; set; } 
    string FromEmailAddress { get; set; } 
} 

public class Email : IEmail 
{ 
    public string FromName { get; set; } 
    public string FromEmailAddress { get; set; } 

    public Email(string fromName, string fromEmailAddress) 
    { 
     FromName = fromName; 
     FromEmailAddress = fromEmailAddress; 
    } 
} 

public class OperationEntity 
{ 
    private readonly IEmail _email; 

    public int OperationId { get; set; } 
    public string OperationName { get; set; } 
    public string ToAddress { get; set; } 

    public OperationEntity(IEmail email) 
    { 
     _email = email; 
    } 

    public void PerformAction() 
    { 
     _email.ToAddress = ToAddress; 
     _email.Body = "Some email body"; 
     _email.Deliver(); 
    } 
} 

Qualsiasi aiuto sarebbe apprezzato a ottenere questo codice Unità di lavorare

public static void Register(IUnityContainer container) 
    { 
     container 
      .RegisterType<IEmail, Email>(
      new InjectionFactory(c => new Email(
       "To Name", 
       "[email protected]"))); 

     var email = container.Resolve<IEmail>(); 

     container.RegisterType<OperationEntity>(
      "email", new ContainerControlledLifetimeManager(), 
      new InjectionConstructor(email)); 
    } 
+0

Stavo cercando aiuto con il codice C# Unity necessario per collegarlo. – Bern

+0

Forse il [wiki su Singleton] (http://wiki.unity3d.com/index.php/Singleton) avrebbe potuto essere di qualche aiuto. – cregox

+0

@cregox Questo è un collegamento a Unity3d, una libreria grafica. Questa è una domanda sul [Unity container] (https://msdn.microsoft.com/en-us/library/ff647202.aspx), un framework DI. – Andy

risposta

27

In primo luogo, è necessario un adeguato lifetime manager il ContainerControlledLifetimeManager è per single.

Per l'inizializzazione personalizzato, probabilmente si potrebbe utilizzare InjectionFactory

Questo consente di scrivere alcun codice che inizializza l'entità.

Edit1: questo dovrebbe aiutare

public static void Register(IUnityContainer container) 
{ 
    container 
     .RegisterType<IEmail, Email>(
     new ContainerControlledLifetimeManager(), 
     new InjectionFactory(c => new Email(
      "To Name", 
      "[email protected]"))); 
} 

e poi

var opEntity = container.Resolve<OperationEntity>(); 

Edit2: Per supportare la serializzazione, che avrebbe dovuto ricostruire le dipendenze dopo si deserializzare:

public class OperationEntity 
{ 
    // make it public and mark as dependency 
    [Dependency] 
    public IEmail _email { get; set;} 

} 

e then

OperationEntity entity = somehowdeserializeit; 

// let unity rebuild your dependencies 
container.BuildUp(entity); 
+0

Ho usato la logica del secondo collegamento per risolvere un'istanza di posta elettronica, ma come faccio a garantire che OperationEntity userà quell'istanza nel suo costruttore? Ho provato container.RegisterType (nuovo InjectionConstructor (email)); ma senza fortuna. – Bern

+0

Se si utilizza ContainerControlledLifetimeManager, l'unica entità singleton verrà sempre iniettata nei costruttori di altre classi. –

+0

Ho incluso il mio codice sopra usando i tuoi suggerimenti, sfortunatamente ottengo ancora un valore nullo per l'istanza di email nel costruttore OperationEntity quindi suppongo di aver perso qualcosa. Potrei disturbarti per i tuoi pensieri. – Bern

11

si può usare:

container.RegisterType<IEmail, Email>(new ContainerControlledLifetimeManager()); 
6

Se IEmail è un singoletto senza dipendenze (solo argomenti personalizzati), è possibile nuovo su voi stessi:

container.RegisterInstance<IEmail>(new Email("To Name", "[email protected]")); 

che registrerà l'istanza fornito come un singleton per il contenitore.

Poi basta risolvere il servizio:

container.Resolve<OperationEntity>(); 

E perché si sta risolvendo un tipo concreto, non v'è nessuna registrazione richiesta. Tuttavia, se vuoi che il servizio di essere anche un singleton, è possibile registrarsi utilizzando ContainerControlledLifetimeManager e poi tutte le chiamate a risolvere (o quando l'iniezione come una dipendenza ad un'altra classe) restituirà la stessa istanza:

container.RegisterType<OperationEntity>(new ContainerControlledLifetimeManager()); 
+1

Grazie per questo. Alla fine è stata la deserializzazione di OperationEntity che è stato il problema principale, e non sono sicuro che questo approccio risolva questo problema. Il codice necessario dopo la deserializzazione era unityContainer.BuildUp (OperationEntity); – Bern