2012-09-26 18 views
8

Estoy construyendo un pequeño proyecto web de Nancy.Obtención del contenedor actual TinyIoc en un proyecto de Nancy

En un procedimiento de una de mis clases (no es un módulo de Nancy), me gustaría básicamente hacer:

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

Sin embargo, sólo hay una inscripción en .Current (miembros no públicos, _RegisteredTypes), que es:
TinyIoC.TinyIoCContainer.TypeRegistration

Naturalmente, en mi código anterior, que estoy recibiendo:

No se puede resolver tipo: My.Namespace.IMyThing

Entonces, supongo que no estoy obteniendo el mismo contenedor registrado en mi bootstrapper?

¿Hay alguna manera de conseguirlo?

EDITAR

para dar cuerpo a un poco más de lo que yo estoy tratando de hacer:

Básicamente, mi estructura de la URL tiene la siguiente apariencia:

/{} myType/{myMethod}

Entonces, la idea es, yendo a:/customer/ShowAllWithTheNameAlex cargar el Customer servicio, y ejecutar el método showAllWithTheNameAlex

¿Cómo hago esto es:

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

entonces tienen una clase base abstracta, con un GetService método que devuelve el servicio.
Aquí estoy tratando de usar el TinyIoC.TinyIoCContainer.Current.Resolve();
En este caso, sería 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.... 
    } 
} 

Aquí está mi implementación del servicio.

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

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

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

Por último, tengo mi Módulo Nancy, que se parece 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 
    } 
} 

Respuesta

4

@alexjamesbrown - La respuesta corta es que no lo hacen. Nancy fue diseñada específicamente para que no manejes el contenedor directamente. Menciona que la clase, que desea tomar una dependencia en IMyThing, no es un NancyModule. Bueno, esto no es un problema, siempre y cuando uno de sus módulos tenga una referencia al mismo, entonces esas dependencias también pueden tener sus propias dependencias que se satisfarán en el tiempo de ejecución.

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

Lo anterior funcionará bien y Greeter tendrá su dependencia de IGreetingMessageService satisfecho en tiempo de ejecución

+0

Gracias por su respuesta .... Creo que estamos llegando He desarrollado mi pregunta para ilustrar exactamente lo que estoy tratando de hacer ... ¡ojalá tenga más sentido! – Alex

+0

Como realizó una publicación cruzada en nuestro grupo de usuarios, proporcioné una explicación más detallada allí https://groups.google.com/d/topic/nancy-web-framework/FVuM9kIiI7Q/discussion – TheCodeJunkie

-1

En este caso particular, "no se trata de contenedor directamente" es muy problemático:

interfaz pública IFoo {}

public class Foo: {IFoo pública Foo (barra de cadena) {}}

Supongamos que ya es una dependencia del constructor de un módulo de Nancy.

Tenga en cuenta la dependencia de cadena del constructor Foo. Necesito comunicarme con el contenedor para usar ese constructor para un singleton IFoo, cuando me encuentro con una dependencia de módulo de Nancy. Necesito registrar eso en la instancia de TinyIoC que utiliza NancyFx, y pasar el valor real de la barra.

0

He tenido un problema muy similar, la necesidad de "compartir" el contenedor. La razón por la cual este es un problema es que mi programa se ejecuta como un servicio que utiliza el alojamiento propio de Nancy para proporcionar una API REST. Mis módulos tienen dependencias que son inyectadas por Nancy, pero las otras partes de la aplicación que no están referenciadas desde los módulos también necesitan dependencias inyectadas. Múltiples contenedores no son una opción sensata aquí (o en cualquier lugar realmente), necesito compartir el contenedor entre Nancy y el resto de la aplicación.

simplemente hizo lo siguiente (estoy usando Autofac pero sospecho que en TinyIoC similares)

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

Entonces, en mi código principal, puede utilizar el contenedor mismo

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

Como mi NancyHost está dentro del Servicio, el contenedor se construye (una vez) después de su primer uso en main, esta estática se usa cuando Nancy se da la vuelta para crear el Bootstrapper.

En un mundo ideal, realmente no quisiera un contenedor accesible globalmente, normalmente sería local para la función main.

Cuestiones relacionadas