2016-03-28 21 views
0

Gibt es eine Möglichkeit ich folgende in einem kürzeren Weg acheieve kann als explizit diese Typen einzeln registrieren:Autofac Schlüssel Registrierungen

builder.RegisterType<Repo1>().Keyed<IRepository>(typeof(Repo1)); 

builder.RegisterType<Repo2>().Keyed<IRepository>(typeof(Repo2)); 

builder.RegisterType<Repo3>().Keyed<IRepository>(typeof(Repo3)); 

..

jedes Repository als IRepository Schnittstelle mit seiner Art Registrieren als Schlüssel, so dass ich IIndex<Type, IRepository>

Vielen Dank im Voraus

+0

Warum benutzen Sie 'RegisterGeneric' nicht? –

+0

Jedes Repository erbt von einem BaseRepository und von einer bestimmten Schnittstelle. Wie registriere ich all diese Repositories als generisch? –

+0

Ich verstehe. Aber ich bleibe bei meinem Kommentar unten, getippte Registrierung und Auflösung von Repositories innerhalb der Einheit des Arbeitsobjekts ist nicht etwas, was ich tun würde. –

Antwort

0

Nicht wirklich sicher, ob ich folgende bin die Frage c verwenden kann Normalerweise verweist das Repository jedoch auf ein Daten-Repository mit generischen Funktionen (Einfügen, Aktualisieren, Löschen usw.). autofac keyed services wird jedoch verwendet, um den Dienst mit Schlüsselnamen (oder einem beliebigen Schlüsseltyp) zu registrieren. Wenn dies der Fall ist, müssen Sie eine Lösung finden, die alle Ihre Repo Typen finden und sie einzeln in einer Schleife registrieren kann. Dies könnte mit Reflection erreicht werden. Jedoch wird jedes Objekt Repo1, Repo2 usw., eine gemeinsame Ableitung benötigen.

Zum Beispiel kann sagen, dass jedes Objekt Repo derrives von der Schnittstelle IRepo dann können wir Reflektion verwenden, um alle Instanzen der IRepo Schnittstelle zu finden, wo der Typ a class dann Schleife durch jede Instanz, um sie Ihren Behälter zu registrieren. Etwas wie.

var iRepoType = typeof(IRepo); 
var repoTypes = Assembly.GetExecutingAssembly().GetTypes() 
               .Where(type => type.IsClass && iRepoType.IsAssignableFrom(type)) 
               .ToList(); 

foreach(var repoType in repoTypes) 
{ 
    builder.RegisterType(repoType).Keyed<IRepository>(repoType); 
} 

Jetzt persönlich dies macht keinen Sinn, wie wenn Sie in diesem Schlüsseldienst schauen Sie sagen, wenn ich in der Schlüssel typeof(Repo1) passieren Ich möchte Repo1. Ist das nicht das Gleiche, als wenn Sie jeden Repository-Typ ohne Keyed Services unterschiedlich registrieren würden?

Ich habe eine Antwort in Code-Review im Gespräch über Repository patterns and classes, die auch ein wenig Interesse sein kann geschrieben.

+0

Ich habe ein einfaches generisches Repository, von dem jedes Repository erbt.Außerdem habe ich für jedes Repository eine andere Schnittstelle mit der passenden Methode für die Entität erstellt. Jetzt möchte ich alle diese Repositories registrieren, um sie in meiner Einheit oder Arbeit zu haben –

+0

Ich möchte eine Fabrik von Repositories in meiner Arbeitseinheit haben –

+0

Einheit der Arbeit wird dann Ihren Container als Service-Locator verwenden. Dies ist völlig unnötig, da Ihre Dienste zusammen mit der Arbeitseinheit Repositories injizieren können. Sie müssen nur den passenden Lifetime-Bereich ermitteln, damit Sie eine Einheit der Arbeitsinstanz für alle Repositories in einer, also einer Arbeitseinheit, erhalten. –

1

Sie könnten eine Funktion registrieren, die ein Repository für einen bestimmten Typ zur Verwendung in Ihrer Arbeitseinheit zurückgibt. Func<Type, IRepository> kann in Autofac registriert und in Ihre Arbeitseinheit eingegeben werden.

// register your services as per Nico's answer 
builder.Register... 

// register a factory with Autofac 
builder.Register<Func<Type, IRepository>>(x => { 
    var context = x.Resolve<IComponentContext>(); 
    return y => { 
     return (IRepository) context.Resolve(y); 
    }; 
}); 

// use the factory in your Unit of Work 
class UnitOfWork 
{ 
    readonly Func<Type, IRepository> _factory; 

    public void SomeMethod(object o) 
    { 
     var repository = _factory(o.GetType()); 
     repository.DoSomething(o); 
    } 
} 
0

eine wenig Inspiration von MEF machen, ich habe ein ähnliches "Export Attribut" erstellt diese in Autofac zu erreichen. Sie können ein Export-Attribut erstellen und auf jede Implementierung von IRepository verwenden als

[Export (typeof (IRepository))]

.

Zum Zeitpunkt der Registrierung, einfach extrahieren Sie den Typ und mit RegisterGeneric(), registrieren Sie Ihre Komponenten.

/// <summary> 
/// Export attribute to allow registering components using autofac. 
/// This attribute must be used for all pluggable components that require to be discovered dynamically. 
/// </summary> 
[AttributeUsage(AttributeTargets.Class)] 
public class ExportAttribute:Attribute 
{ 
    private Type type; 

    public ExportAttribute(Type type) 
    { 
     this.type = type; 
    } 

    /// <summary> 
    /// Provides the type (any interface) of Export 
    /// </summary> 
    public Type Type { get { return this.type; } } 
} 

    /// <summary> 
    /// Registers components based on Export attribute containing their type information 
    /// </summary> 
    private void BuildContainer() 
    { 
     var allAssemblies = AssemblyInitializer.GetLoadedPlugins(); 
     allAssemblies.ForEach(assembly => 
     { 
      var allTypes = assembly.GetTypes().Where(a => a.GetCustomAttribute(typeof(ExportAttribute)) != null).ToList<Type>();    

      allTypes.ForEach(y => 
      { 
       var classType = ((ExportAttribute)(y.GetCustomAttribute(typeof(ExportAttribute)))).Type; 

       if (!classType.IsInterface || !classType.IsAbstract || !classType.IsPublic) return; 

       if (classType.Equals(typeof(IRepository<>))) 
       { 
        builder.RegisterGeneric(y.GetTypeInfo()).Named(y.GetTypeInfo().Name, typeof(IRepository<>)); 
       } 
       // Handle code for any other specific Interfaces       
      }); 


     }); 

     this.Container = builder.Build(); 
    }