2011-01-31 7 views
7

Ho le seguenti interfacce:Autofac. Come utilizzare il metodo personalizzato (proprietà) per risolvere alcune interfacce?

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

Ho il seguente attuazione 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 
      } 
     } 

posso anche avere classi distinte di attuazione interfaccia 'ISettings. Ad esempio,

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

Sto utilizzando il seguente codice per configurare 'ContainerBuilder': builder.RegisterGeneric(typeof(ConfigurationProvider<>)).As(typeof(IConfigurationProvider<>));

Funziona benissimo. E al fine di ottenere 'UserSettings' Io uso il seguente codice:

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

La domanda: come dovrei configurare 'ContainerBuilder' in modo da poter risolvere un certo 'ISettings' nel seguente modo:

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

È possibile con Autofac?

Grazie in anticipo

risposta

5

Si può fare questo con un IRegistrationSource - vedere http://nblumhardt.com/2010/01/declarative-context-adapters-autofac2/ per una panoramica.

La struttura di base sarebbe:

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

Questa è registrato in questo modo:

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

(non compilato o testati, quindi fatemi sapere se cade sopra;))

+0

Grazie per la risposta. Sto cercando il seguente errore di compilazione "Impossibile convertire implicitamente il tipo 'Autofac.Builder.IRegistrationBuilder ' a 'Autofac.Core.IComponentRegistration'" nel tuo metodo BuildRegistration() . –

+0

Funziona come un fascino. Grazie. Post scriptum Hai dimenticato di aggiungere .CreateRegistration() nel metodo "BuildRegistration ()" –

+0

Nickolas, un'altra domanda. Attualmente l'istanza 'ISetting' viene creata per dipendenza (comportamento predefinito). Come posso cambiarlo in 'InstancePerLifetimeScope' o 'InstancePerHttpRequest' ('Autofac.Integration.Mvc.dll' è già stato aggiunto) –

Problemi correlati