2011-01-31 14 views
7

que tienen las siguientes interfaces:Autofac. ¿Cómo usar el método personalizado (propiedad) para resolver alguna interfaz?

public interface IConfigurationProvider<TSettings> where TSettings : ISettings, new() 
{ 
     TSettings Settings { get; } 
} 
public interface ISettings 
{ 
} 

tengo la siguiente implementación de IConfigurationProvider:

public class ConfigurationProvider<TSettings> : IConfigurationProvider<TSettings> where 

    TSettings : ISettings, new() 
     { 
      public ConfigurationProvider() 
      { 
       this.BuildConfiguration(); 
      } 

      public TSettings Settings { get; private set; } 

      private void BuildConfiguration() 
      { 
       this.Settings = new TSettings(); 
       //...load and assign properties to 'this.Settings' 
       //...skipped 
       // now 'Settings' property contains configured 'ISettings' instance 
      } 
     } 

también puedo tener clases distintas de aplicación de interfaz '' ISettings. Por ejemplo,

public class UserSettings : ISettings 
    { 
     public int SomeProperty1 { get; set; } 
     public int SomeProperty2 { get; set; } 
    } 


public class CatalogSettings : ISettings 
    { 
     public int SomeProperty3 { get; set; } 
     public int SomeProperty4 { get; set; } 
    } 

estoy usando el siguiente código para configurar 'ContainerBuilder': builder.RegisterGeneric(typeof(ConfigurationProvider<>)).As(typeof(IConfigurationProvider<>));

Trabaja muy bien. Y con el fin de conseguir 'UserSettings' Yo uso el siguiente código:

var userSettingsProvider = builder.Resolve<IConfigurationProvider<UserSettings>>(); 
var userSettings = userSettingsProvider.Settings; 

La pregunta: ¿cómo debo configurar 'ContainerBuilder' para que pueda resolver una cierta 'ISettings' de la siguiente manera:

var userSettings = builder.Resolve<UserSettings>(); 

¿Es posible con Autofac?

Gracias de antemano

Respuesta

5

Usted puede hacer esto con un IRegistrationSource - ver http://nblumhardt.com/2010/01/declarative-context-adapters-autofac2/ para una visión general.

La estructura básica sería:

class SettingsSource : IRegistrationSource { 
    static readonly MethodInfo BuildMethod = typeof(SettingsSource).GetMethod(
     "BuildRegistration", 
     BindingFlags.Static | BindingFlags.NonPublic); 

    public IEnumerable<IComponentRegistration> RegistrationsFor(
      Service service, 
      Func<Service, IEnumerable<IComponentRegistration>> registrations) { 
     var ts= service as TypedService; 
     if (ts != null && typeof(ISettings).IsAssignableFrom(ts.ServiceType) { 
      var buildMethod = BuildMethod.MakeGenericMethod(ts.ServiceType); 
      yield return (IComponentRegistration) buildMethod.Invoke(null, null); 
     } 
    } 

    static IComponentRegistration BuildRegistration<TSettings>() 
      where TSettings : ISettings { 
     return RegistrationBuilder 
      .ForDelegate((c, p) => 
       c.Resolve<IConfigurationProvider<TSettings>>().Settings) 
      .CreateRegistration(); 
    } 

    public bool IsAdapterForIndividualComponents { get { return false; } } 
} 

Esto se registra como tal:

builder.RegisterGeneric(typeof(ConfigurationProvider<>)) 
    .As(typeof(IConfigurationProvider<>)); 
builder.RegisterSource(new SettingsSource()); 

(no compilados o probada, por lo que me haga saber si se cae;))

+0

Gracias por responder. Me aparece el siguiente error de compilación "No se puede convertir implícitamente el tipo 'Autofac.Builder.IRegistrationBuilder ' en 'Autofac.Core.IComponentRegistration'" en el método BuildRegistration() . –

+0

Funciona como un encanto. Gracias. PD Olvidó agregar .CreateRegistration() en el método "BuildRegistration ()" –

+0

Nickolas, una pregunta más. Actualmente se crea la instancia 'ISetting' por dependencia (comportamiento predeterminado). ¿Cómo podría cambiarlo a 'InstancePerLifetimeScope' o 'InstancePerHttpRequest' ('Autofac.Integration.Mvc.dll' ya está agregado) –

Cuestiones relacionadas