2010-07-07 23 views
25

estoy registrar componentes con el siguiente código:Volver misma instancia de múltiples interfaces

StandardKernel kernel = new StandardKernel(); 

string currentDirectory = Path.GetDirectoryName(GetType().Assembly.Location) 
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) 
{ 
    if (!Path.GetDirectoryName(assembly.Location).Equals(currentDirectory)) 
     continue; 

    foreach (var type in assembly.GetTypes()) 
    { 
     if (!type.IsComponent()) 
      continue; 

     foreach (var @interface in type.GetInterfaces()) 
     kernel.Bind(@interface).To(type).InSingletonScope(); 
    } 
} 

Entonces tengo una clase que implementa dos interfaces:

class StandardConsole : IStartable, IConsumer<ConsoleCommand> 

Si puedo resolver IStartable consigo uno Por ejemplo, si resuelvo IConsumer<ConsoleCommand> obtengo otro.

¿Cómo obtengo la misma instancia para ambas interfaces?

+1

Esta pregunta debe dividirse en dos, una para Ninject y otra para autofac. –

+0

@JeffWalkerCodeRanger: ¿Has dado -1 por eso? :) – jgauffin

+1

Hay 3 o 4 dups en el lado de Ninject, ver http://stackoverflow.com/questions/3147996/binding-singleton-to-multiple-services-in-ninject Se eliminó la etiqueta de ninject sobre esa base. Sugerir la eliminación de aspecto ninject de la pregunta ya que esto hace una pregunta sin respuesta –

Respuesta

49
builder.RegisterType<StandardConsole>() 
    .As<IStartable>() 
    .As<IConsumer<ConsoleCommand>>() 
    .SingleInstance(); 

muy ampliamente utilizado de Autofac- algún problema, hay un error en alguna parte :)

HTH Nick

Editar Por el parece que está buscando la sobrecarga de As() que toma un IEnumerable <Tipo>(): revisa todas las sobrecargas de As() usando IntelliSense, algo que debería encajar en tu situación. Como señaló otro comentarista, debe actualizar la pregunta con toda la información.

+0

No, no deseo registrarme usando IEnumerable . Es una función integrada en autofac. Además, no puedo usar parámetros genéricos ya que estoy usando la reflexión para registrar todos los componentes. – jgauffin

+2

Sé a qué característica te refieres (la escribí;)) - la que estoy sugiriendo es diferente. Si tiene una lista de las interfaces que desea exponer (i1, i2, i3 ...) puede pasar la lista completa a una única llamada As(). También puede consultar RegisterAssemblyTypes (myAsm) .AsImplementedInterfaces(), que se puede ampliar para hacer lo que su artículo propone http://code.google.com/p/autofac/wiki/Scanning: le invitamos a que trabaje a través de esto a través del foro de discusión Autofac si quieres. –

+0

Lo siento =) Simplemente me cansé de la respuesta de las personas que no habían usado autofac. He actualizado mi respuesta a continuación con el código del artículo de Escaneo. ¡Gracias! – jgauffin

0

Este soy yo tomando una puñalada salvaje en la oscuridad ya que no conozco Autofac.

Si añade:

build.RegisterType<StandardConsole>.As(StandardConsole).SingleInstance() 

entonces no habría de resolver IStartable a continuación StandardConsole StandardConsole a la instancia singleton de StandardConsole? Ídem con IConsumidor.

EDIT: Desde el registro en su blog, podría no cambiar lo siguiente:

assemblies.Each(assembly => assembly.FindComponents((i, c) => builder.RegisterType(c).As(i).SingleInstance())); 

a

assemblies.Each(assembly => assembly.FindComponents((i, c) => { 
    builder.RegisterType(c).As(i).SingleInstance(); 
    builder.RegisterType(c).As(c).SingleInstance(); 
})); 
+0

Ver mi comentario para dave thieben – jgauffin

0

No estoy familiarizado con Autofac, pero usted debería ser capaz de Registre para un tipo una expresión lambda que devuelve la resolución del otro tipo.

algo como: función

builder.Register<IStartable>().As<StandardConsole>().Singleton(); 
builder.Register<IConsumer<ConsoleCommand>>().As(x => builder.Resolve<IStartable>()); 
+1

No se puede hacer.Escaneo todos los ensamblajes en el directorio de la aplicación después de las clases con un ComponentAttribute y los registro con todas las interfaces que implementan. Eso hace que sea bastante difícil hacer lo que sugieres. http://blog.gauffin.org/2010/07/simplified-autofac-registrations/ – jgauffin

2

Actualizado con la sugerencia de Nicolás:

Aquí es cómo se hace en autofac

private void BuildComponents(ContainerBuilder builder) 
    { 
     string currentDirectory = Path.GetDirectoryName(GetType().Assembly.Location); 
     foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies()) 
     { 
      if (!Path.GetDirectoryName(assembly.Location).Equals(currentDirectory)) 
       continue; 

      builder.RegisterAssemblyTypes(assembly) 
       .Where(t => t.IsComponent()) 
       .AsImplementedInterfaces() 
       .SingleInstance(); 
     } 
    } 

    public static bool IsComponent(this Type value) 
    { 
     return value.GetType().GetCustomAttributes(typeof (ComponentAttribute), true).Length > 0; 
    } 
2

Sé que esto es un viejo hilo, pero aquí es la solución para Ninject.

kernel.Bind<StandardConsole>().ToSelf().InSingletonScope(); 
kernel.Bind<IStartable>().ToMethod(ctx => ctx.Kernel.Get<StandardConsole>()); 
kernel.Bind<IConsumer<ConsoleCommand>>().ToMethod(ctx => ctx.Kernel.Get<StandardConsole>()); 
+0

Esto no funciona cuando se usa ActivationContext. –

+0

@Jeff: ver http://www.planetgeek.ch/2011/12/30/new-features-and-changes-of-ninject-3-0/ –

Cuestiones relacionadas