2010-10-31 5 views
6
public interface IRepository<T> where T : Entity 
{ 
    void Delete(T entity); 
    T[] GetAll(); 
    T GetById(int id); 
    void SaveOrUpdate(T enity); 
    void Merge(T entity); 
} 

public interface ITeamEmployeeRepository : IRepository<TeamEmployee> 
{ 
    PagedList<TeamEmployee> GetPagedTeamEmployees(int pageIndex, int pageSize); 
} 


public class Repository<T> : IRepository<T> where T : Entity 
{ 
    private readonly ISession _session; 

    protected Repository() 
    { 
     _session = GetSession(); 
    } 

    public virtual void Delete(T entity) 
    { 
     _session.Delete(entity); 
    } 

    public virtual T[] GetAll() 
    { 
     return _session.CreateCriteria<T>().List<T>().ToArray(); 
    } 

    public virtual T GetById(int id) 
    { 
     return _session.Get<T>(id); 
    } 

    public virtual void SaveOrUpdate(T enity) 
    { 
     _session.SaveOrUpdate(enity); 
    } 

    public void Merge(T entity) 
    { 
     _session.Merge(entity); 
    } 

    protected ISession GetSession() 
    { 
     return new SessionBuilder().GetSession(); 
    } 
} 

public class TeamEmployeeRepository : Repository<TeamEmployee>, ITeamEmployeeRepository 
{ 
    public PagedList<TeamEmployee> GetPagedTeamEmployees(int pageIndex, int pageSize) 
    { 
     return GetSession().QueryOver<TeamEmployee>() 
      .Fetch(x => x.Employee).Eager 
      .Fetch(x => x.Team).Eager 
      .ToPagedList(pageIndex, pageSize); 
    } 
} 

Vorerst registrieren und lösen registriere ich das Repository wie folgt:StructureMap - Wie ein offenen generischen Typen

For<ILoanedItemRepository>().Use<LoanedItemRepository>(); 
For<ITeamEmployeeRepository>().Use<TeamEmployeeRepository>(); 
For<IArticleRepository>().Use<ArticleRepository>(); 
For<ISalesmanRepository>().Use<SalesmanRepository>(); 
For<ISalesmanArticleRepository>().Use<SalesmanArticleRepository>(); 
For<IGoodsGroupRepository>().Use<GoodsGroupRepository>(); 
For<IEmployeeRepository>().Use<EmployeeRepository>(); 

Das ist wirklich umständlich ist, vor allem, wenn es entlang der neuen Repositories kommt.

Eine einfachere und bessere Registrierung wäre:

For(typeof(IRepository<>)).Use(typeof(Repository<>)); 

Aber das funktioniert nicht. StructureMap sagt mir immer, dass keine Default Instance für PluginFamily Core.Domain.Bases.Repositories.ITeamEmployeeRepository definiert wurde.

suchte ich auf Stackoverflow und fand etwas Neues:

Scan(x => 
{ 
    x.AssemblyContainingType(typeof(TeamEmployeeRepository)); 
    x.AddAllTypesOf(typeof (IRepository<>)); 
    x.ConnectImplementationsToTypesClosing(typeof(IRepository<>)); 
}); 

aber immer noch die gleiche Fehlermeldung.

Wie muss ich meine Repositorys mit StructureMap 2.6.1.0 registrieren?

+0

Während dies Ihre Frage nicht direkt beantwortet, werfen Sie einen Blick auf diesen Artikel: http://StackOverflow.com/Questions/4128640/How-to-Remove-Unit-of-Funktion-Funktions-von-Repositories-Verwendung -ioc/41 32186 # 4132186. Es zeigt eine alternative Möglichkeit, das Repository-Muster zu implementieren. Die Implementierung verbirgt Ihre Repositories hinter einer Arbeitseinheit und Sie müssen nur eine "IUnitOfWorkFactory" registrieren und Sie sind fertig. – Steven

Antwort

7

Ich habe eine Lösung gefunden.

Scan(x => 
{ 
    x.WithDefaultConventions(); 
    x.AssemblyContainingType(typeof(TeamEmployeeRepository)); 
    x.AddAllTypesOf(typeof(Repository<>)); 
    x.ConnectImplementationsToTypesClosing(typeof(IRepository<>)); 
}); 

WithDefaultConventions ist der wichtige Teil des gezeigten Code, denn mit dieser Einstellung können Sie sagen StructureMap die Konvention verwenden ITeamEmployeeRepository zu TeamEmployeeRepository mappping. So geht StructureMap von der Annahme aus, dass die Klasse wie der Name der Schnittstelle ohne das Präfix I benannt ist.

-1

Ich habe vor kurzem etwas ähnliches gelöst, indem ich ein kleines Redesign gemacht habe, was alles so viel einfacher gemacht hat. Dies könnte auch für Sie funktionieren. Sie könnten versuchen, die spezifischen Schnittstellen wie ITeamEmployeeRepository und ILoanedItemRepository aus Ihrem Design zu entfernen. Die Art, wie ich das gemacht habe, war mit Erweiterungsmethoden. Hier ein Beispiel:

public static class RepositoryExtensions 
{ 
    public static TeamEmployee GetById(
     this IRepository<TeamEmployee> repository, int id) 
    { 
     return repository.Single(e => e.TeamEmployeeId == id); 
    } 

    public static IQueryable<Salesman> GetActiveSalesmen(
     this IRepository<ISalesmanRepository> repository) 
    { 
     return repository.Where(salesman => salesman.Active); 
    } 

    // etc 
} 

Danach habe ich eine IRepositoryFactory erstellt, die mir erlaubt Repositorys eines bestimmten Typs zu schaffen:

public interface IRepositoryFactory 
{ 
    IRepository<T> CreateNewRepository<T>(); 
} 

Wenn diese Schnittstelle an Ort und Stelle mit ist es einfach eine Implementierung zu erstellen Diese Fabrik, die den Container auffordert, einen Beton Repository<T> zu erstellen. Die RepositoryFactory könnte wie folgt aussehen:

public class RepositoryFactory : IRepositoryFactory 
{ 
    public IRepository<T> CreateNewRepository<T>() 
    { 
     return ObjectFactory.GetInstance(typeof(Repository<T>)); 
    } 
} 

Mit diesem Entwurf erhalten Sie nur über die konkrete RepositoryFactory durch seine IRepositoryFactory Schnittstelle registrieren und Sie sind fertig. Anstatt IRepository<ITeamEmployeeRepository> in das alte Design zu injizieren, injizieren Sie jetzt eine IRepositoryFactory und lassen den Client die CreateNewRepository<T> Methode aufrufen. Wegen der Verwendung von Erweiterungsmethoden können Sie typspezifische Methoden im Repository aufrufen.

Ein weiterer Vorteil besteht darin, dass Sie die Methoden, die Sie ursprünglich für alle Implementierungen unter ITeamEmployeeRepository definiert haben, nicht erneut implementieren müssen.

Dieser Entwurf funktionierte sehr gut in meiner Situation, besonders weil meine IRepository<T> Schnittstellen Expressionsbäume verwenden. Natürlich kann ich nicht sehen, ob ein solches Design für Sie funktioniert, aber ich hoffe es.

Viel Glück.

+0

"Ein weiterer Vorteil besteht darin, dass Sie die Methoden, die Sie ursprünglich für ITeamEmployeeRepository definiert haben, nicht bei jeder Implementierung neu implementieren müssen." Dies ist nicht der Fall, da das Repository bereits das CRUD-Standardmaterial implementiert. Das spezifische ITeamEmployeeRepository hat nur bestimmte Anforderungen. – Rookian

+0

Vielleicht missverstehe ich, aber ich stellte mir vor, dass Sie das 'ITeamEmployeeRepository' für teammitarbeiterspezifische Methoden verwenden würden. Diese Methoden hätten in der Klasse "Repository " keine Bedeutung. Ich nehme an, Sie haben an dieser Schnittstelle entitätsspezifische Methoden, weil eine Schnittstelle ohne Methoden nicht sehr nützlich wäre. Dinge wie 'GetByYear' oder CRUD-Operationen, die keine Bedeutung für Repository haben. Normalerweise hätten Sie mindestens zwei Implementierungen dieser 'ITeamEmployeeRepository'-Schnittstelle ... – Steven

+0

Eine in Ihrer Produktionsumgebung und eine für Ihre Einheitentestumgebung. Dies bedeutet, dass Sie in diesen Situationen 'GetByYear' sowohl in Ihrer Produktion 'TeamEmployeeRepository' als auch im verwendeten Test-Repository implementieren müssen. Mit einer Erweiterungsmethode ersparen Sie sich nicht nur das mehrfache Schreiben, sondern Sie können diesen Code auch abdecken. Aber vielleicht verstehe ich deine Bedürfnisse falsch. – Steven

-2

Sie müssen Ihre eigene ITypeScanner erstellen und in Ihrem Scan() Anruf registrieren. Sehen Sie sich den Quellcode GenericConnectionScanner als Ausgangspunkt an. Anstatt nach den Typen zu suchen, um zu sehen, ob sie IRepository<T> implementieren, werden Sie nachsehen, ob sie eine Schnittstelle implementieren, die IRepository<T> implementiert, und dann den Typ für diese Schnittstelle registrieren.

UPDATE: Das ganze Gespräch von IRepository<T> ließ mich das überdenken, wenn es wirklich eine irrelevante Details ist. Verwenden Sie einfach den von Rookian vorgeschlagenen DefaultConventions-Scanner.

2

Ich fand diese Frage googeln "Strukturkarte auflösen generisch". Die vorhandenen Antworten sind gut, aber komplex. Für diejenigen, die einfache Antwort: für Interface ISome und implementierende Klasse Einige schreiben wir

c.For<ISome>().Use<Some>() 

Während für generische ISome <T> und implementierende Klasse Einige <T> wir

c.For(typeof(ISome<>)).Use(typeof(Some<>)) 

schreiben und das ist alles