2012-09-26 5 views
8

Sto costruendo un piccolo progetto web Nancy.Ottenere TinyIoc contenitore corrente in un progetto Nancy

In un metodo di una delle mie classi (non un modulo di Nancy), vorrei fondamentalmente fare:

var myThing = TinyIoC.TinyIoCContainer.Current.Resolve<IMyThing>(); 

Tuttavia, v'è una sola iscrizione nel .Current (membri non pubblici, _RegisteredTypes), che è:
TinyIoC.TinyIoCContainer.TypeRegistration

Naturalmente, nel mio codice di cui sopra, mi sto:

in grado di risolvere tipo: My.Namespace.IMyThing

Quindi, suppongo che non sto ottenendo lo stesso contenitore registrato nel mio bootstrapper?

C'è un modo per arrivarci?

EDIT

per rimpolpare un po 'più di quello che sto cercando di fare:

In sostanza, la mia struttura url sembra qualcosa di simile:

/{} myType/{myMethod}

Quindi, l'idea è, andando a:/customer/ShowAllWithTheNameAlex caricare il Customer servizio, ed eseguire il metodo di showAllWithTheNameAlex

Come faccio questo è:

public interface IService 
{ 
    void DoSomething(); 
    IEnumerable<string> GetSomeThings(); 
} 

Ho poi hanno una classe astratta di base, con un metodo GetService che restituisce il servizio.
È qui che sto cercando di utilizzare TinyIoC.TinyIoCContainer.Current.Resolve();
In questo caso, sarebbe TinyIoC.TinyIoCContainer.Current.Resolve ("typeName");

public abstract class Service : IService 
{ 
    abstract void DoSomething(); 
    abstract IEnumerable<string> GetSomeThings(); 

    public static IService GetService(string type) 
    { 
     //currently, i'm doing this with reflection.... 
    } 
} 

Ecco la mia implementazione del servizio.

public class CustomerService : Service 
{ 
    public void DoSomething() 
    { 
     //do stuff 
    } 

    public IEnumerable<string> GetSomeThings() 
    { 
     //return stuff 
    } 

    public IEnumerable<Customer> ShowAllWithTheNameAlex() 
    { 
     //return 
    } 
} 

Infine, ho il mio modulo di Nancy, che assomiglia a:

public class MyModule : NancyModule 
{ 
    public MyModule() 
    { 
     Get["/{typeName}/{methodName}"] = p => ExecuteMethod(p.typeName, p.methodName); 
    } 

    private dynamic ExecuteMethod(string typeName, string methodName) 
    { 
     var service = Service.GetService(typeName); 

     var result = service.GetType().GetMethod(methodName).Invoke(service, null); 

     //do stuff 

     return result; //or whatever 
    } 
} 

risposta

4

@alexjamesbrown - La risposta breve è che non lo fanno. Nancy è stata specificamente progettata in modo da non avere a che fare direttamente con il container. Si dice che la classe, che si vuole prendere una dipendenza su IMyThing, non è un NancyModule. Beh, questo non è un problema, purché uno dei tuoi moduli abbia un riferimento ad esso, allora quelle dipendenze possono anche avere le loro dipendenze che saranno soddisfatte in fase di runtime.

public interface IGreetingMessageService 
{ 
    string GetMessage(); 
} 

public class GreetingMessageService: IGreetingMessageService 
{ 
    public string GetMessage() 
    { 
     return "Hi!"; 
    } 
} 

public interface IGreeter 
{ 
    string Greet(); 
} 

public class Greeter 
{ 
    private readonly IGreetingMessageService service; 

    public Greeter(IGreetingMessageService service) 
    { 
     this.service = service; 
    } 

    public string Greet() 
    { 
     return this.service.GetMessage(); 
    } 
} 

public class GreetingsModule : NancyModule 
{ 
    public GreetingModule(IGreeter greeter) 
    { 
     Get["/"] = x => greeter.Greet(); 
    } 
} 

È possibile che questo funzionerà bene e Greeter avrà è dipendenza da IGreetingMessageService soddisfatto in fase di esecuzione

+0

Grazie per la risposta .... Pensa che ci stiamo arrivando Ho approfondito la mia domanda per illustrare esattamente cosa sto cercando di fare ... speriamo che abbia un po 'più senso! – Alex

+0

Dato che hai effettuato il cross-post al nostro gruppo di utenti, ho fornito una spiegazione più dettagliata in https://groups.google.com/d/topic/nancy-web-framework/FVuM9kIiI7Q/discussion – TheCodeJunkie

-1

In questo caso particolare "non trattare con il contenitore direttamente" è molto problematico:

interfaccia pubblica IFoo {}

public class Foo: IFoo {public Foo (bar stringa) {}}

Supponiamo che IFoo sia già sia una dipendenza costruttore di un modulo Nancy.

Nota la dipendenza da stringa del costruttore Foo. Devo comunicare al contenitore per utilizzare quel costruttore per un singleton IFoo, quando viene rilevato come dipendenza del modulo Nancy. Devo registrarlo nell'istanza TinyIoC che NancyFx utilizza e passare il valore effettivo della barra.

0

Ho riscontrato un problema molto simile, che è necessario "condividere" il contenitore. Il motivo per cui questo è un problema è che il mio programma viene eseguito come servizio utilizzando Nancy self-hosting per fornire un'API REST. I miei moduli hanno dipendenze che vengono iniettate da Nancy stessa, ma anche le altre parti dell'app che non sono referenziate dai moduli hanno bisogno di dipendenze iniettate. Più contenitori non sono un'opzione sensata qui (o dovunque in realtà), ho bisogno di condividere il contenitore tra Nancy e il resto dell'app.

ho semplicemente fatto la seguente (sto usando, ma ho il sospetto che Autofac TinyIoC in simili)

public class Bootstrapper : AutofacNancyBootstrapper 
{ 
    private static readonly Lazy<ILifetimeScope> container = new Lazy<ILifetimeScope>(RegisterTypes); 
    public static ILifetimeScope Container => container.Value; 

    protected override ILifetimeScope GetApplicationContainer() 
    { 
     return container.Value; 
    } 

    // Create container and register my types 
    private static ILifetimeScope RegisterTypes() 
    { 
     var builder = new ContainerBuilder(); 

     // Register all my own types..... 

     return builder.Build(); 
    } 
} 

Poi, nel mio codice principale, posso usare il contenitore stesso

public class Program 
{ 
    public static void Main(string[] args) 
    { 
     // Resolve main service with all its dependencies 
     var service = Bootstrapper.Container.Resolve<Service>(); 
     service.Run(); 
    } 
} 

Poiché il mio NancyHost è all'interno del servizio, il contenitore è costruito (una sola volta) al primo utilizzo in main, quindi questa statica viene utilizzata quando Nancy si occupa di creare lo stesso Bootstrapper.

In un mondo ideale, non vorrei davvero un contenitore accessibile a livello globale, normalmente sarebbe locale alla funzione main.