0

Ich habe ein paar Repository-Klassen in einem Repository-Projekt, das eine Entity Framework DbContext Typed Basisklasse verwendet.Castle Windsor nicht erstellen/verfügbar machen Basisklasse

Base Class

public class RepositoryBase<TC> : IDisposable 
    where TC : DbContext, new() 
{ 

    public virtual T Get<T>(...) where T : class 
    { 
     ... 
    } 

    // ... additional code 
} 

Mitarbeiter Repo-Schnittstelle

namespace Insight.Repository.Interfaces 
{ 
    public interface IEmployeeRepository 
    { 
     Result CreateEmployee(Employee employee); 
     // ... additional code 
    } 
} 

Mitarbeiter Repo

namespace Insight.Repository.Repositories 
{ 
    public class EmployeeRepository : RepositoryBase<InsightContext>, IEmployeeRepository 
    { 
     public Result CreateEmployee(Employee employee) 
     { 
      return Save(employee); 
     } 
    } 
    // ... additional code 
} 

Ich füge die Repo-Klassen an den Windsor Container innerhalb einer ASP.MVC Website ein mit Installer basierend auf Interfaces innerhalb des Repository-Projekts. Ich habe den Container an dieser Stelle angeschaut und erhalte meine drei Repositories.

public void Install(IWindsorContainer container, IConfigurationStore store) 
    { 
     container.Register(Classes.FromAssemblyNamed("Insight.Repository") 
      .Where(Component.IsInNamespace("Insight.Repository.Repositories")) 
      .WithService.DefaultInterfaces() 
      .LifestyleTransient()); 
    } 

Ich habe versucht, den DbContext wie folgt registrieren, aber ich bekomme die gleichen Ergebnisse.

container.Register(Component.For<DbContext>() 
      .ImplementedBy<InsightContext>() 
      .LifestyleTransient()); 

Dann in meinem ApiController verwende ich dann Property Injektion die Repo-Klasse zu instanziiert, aber ich kann keine der Basisklasse Funktionen Zugriff.

public class EmployeeController : ApiController 
{ 
    public IEmployeeRepository EmployeeRepo { get; set; } 

    [Route("GetEmployee")] 
    public void Get() 
    { 
     var newEmployeeRepo = new EmployeeRepository(); 
    } 
} 

EmployeeRepo hat keinen Zugriff auf die Get() Funktion in der Basisklasse, aber newEmployeeRepo tut.

Dies ist mein erstes Projekt mit Castle.Windsor und ich vermisse eindeutig eine Art Registrierungsschritt, kann es aber herausfinden.

Wenn mir jemand in die richtige Richtung zeigen kann, sehr geschätzt.

Edit:

cls.GetLastName().Dump(); 

Ist dies das Verhalten erwartet: mit dem Code von tym32167

void Main() 
{ 
    var container = new WindsorContainer(); 

    var type = typeof(II); 
    container.Register(Classes.FromAssembly(type.Assembly) 
     .Where(Component.IsInNamespace(type.Namespace)) 
     .WithService.AllInterfaces() 
     .LifestyleTransient()); 

    var cls = container.Resolve<II>().Dump(); 
    cls.GetFirstName().Dump(); 
    cls.GetLastName().Dump(); 
} 

public interface II 
{ 
    string GetFirstName(); 
} 

public class MyClass : II 
{ 
    public string GetFirstName() 
    { 
    return "First Name"; 
    } 

    public string GetLastName() 
    { 
    return "Last Name"; 
    } 
} 

Der Code bricht auf dieser Linie geliefert LINQPad Testen?

Antwort

0

Um Zugang zu den Methoden, die auf der Basisklasse zu erhalten, die Sie benötigen eine Basisschnittstelle zu haben :)

public interface IBaseRepo<T> 
{ 
    T Get(int id); 
    // ... 
} 

public interface IEmployeeRepo : IBaseRepo<Employee> 
{ 
    Employee GetByFirstName(string name); 
    // ... 
} 

Beachten Sie, wie die untergeordnete Schnittstelle die Basisschnittstelle erbt. Daher garantiert jeder Typ, der IEmployeeRepo implementiert, dass er auch IBaseRepo<Employee> implementiert, und wenn Sie einen injizieren, erhalten Sie auch Zugriff auf die Methoden auf der Basisschnittstelle.

Die Tatsache, dass Sie das Basisrepo in einer Basisklasse implementieren, die Ihr konkreter Mitarbeiterrepo erbt, ist nur ein Implementierungsdetail, das der Clientcode nicht kümmern sollte - und jetzt nicht!

+0

Nun, wenn Sie es so sagen, es klingt so offensichtlich. Danke, diese Lösung hat einen Reiz hervorgerufen. – Vazmo

0

Try

.WithService.DefaultInterfaces() 

zu

.WithService.AllInterfaces() 

als Probe zu ersetzen (nur mit LINQPad geprüft)

void Main() 
{ 
    var container = new WindsorContainer(); 

    var type = typeof(II); 
    container.Register(Classes.FromAssembly(type.Assembly) 
      .Where(Component.IsInNamespace(type.Namespace)) 
      .WithService.AllInterfaces() 
      .LifestyleTransient()); 

    container.Resolve<II>().Dump(); 
} 

public interface II 
{ 
} 

public class MyCl : II 
{ 
} 
+0

Ich machte die Änderung wie vorgeschlagen, aber es schien nur die zusätzliche IDisposable-Schnittstelle aus der RepositoryBase-Klasse abzuholen. Betrachtet man den Container nach der Registrierung, hat sich ** EmployeeRepository/IEmployeeRepository = Transient ** zu ** EmployeeRepository/IEmployeeRepository und 1 anderen Services = Transient ** innerhalb der Komponenten des Containers geändert und ich habe einen zusätzlichen ** IDisposable ** -Eintrag innerhalb der Dienste des Containers. Es löst immer noch nicht die Basisklassenfunktionalität auf. – Vazmo

+0

verwenden Sie Webapi, richtig? Implementieren Sie alle nececarry relations Sachen wie dependencyresolver/dependency scope? Sobald ich eine Basisprobe mit Castle Windsor erstellt habe, überprüfe diese bitte https://github.com/typ32167/webapisample (speziell global.asax.cs und Core folder hier https://github.com/tym32167/webapisample/tree/master/ src/Sample/Core) – tym32167

+0

übrigens, Konstruktor Injektion viel besser als Property Injection, weil 1. Sie können alle Abhängigkeiten an einem Ort sehen - ctor Argumente, 2. - bei Problemen mit der Auflösung erhalten Sie Laufzeit Ausnahme mit Nachricht und Stack-Trace – tym32167