2017-08-14 4 views
2

Ich habe eine 2 Controller PayerController und BusinessController. Beide Controller-Konstruktoren verwenden EntityManager als Parameter, der eine abstrakte Klasse ist. Ich möchte jede Manager-Klasse abhängig von dem Controller, den ich verwende, auflösen.Bedingte Abhängigkeitsauflösung in Asp.net Kern

Für PayerController möchte ich PayerManager-Klasse injizieren und für BusinessController möchte ich BusinessManager injizieren.

Derzeit erhalte ich das letzte Objekt, das mit EntityManager aufgelöst wurde, d. H. BusinessManager.

Ich erinnere mich, in Ninject können wir bedingte Injektion ziemlich leicht tun.

Dies ist, wie aktuell ich die Abhängigkeit lösen Aber nicht arbeiten.

Startup.cs

services.AddScoped(typeof(EntityManager), typeof(PayerManager)); 
services.AddScoped(typeof(EntityManager), typeof(BusinessManager)); 

Controller

public class PayerController 
{ 
    private PayerManager Manager{get;} 
    public PayerController(EntityManager entityManager) 
    { 
     Manager = entityManager as PayerManager; 
    } 
} 

Manager-Klassen

public class PayerManager : EntityManager 
{ 
    public void MyPayer() 
    { 
    } 
} 

public class BusinessManager : EntityManager 
{ 
    public void MyBusiness() 
    { 
    } 
} 

public abstract class EntityManager 
{ 
    public string IAMCommon() 
    { 
     return ""; 
    } 
} 
+0

werden Sie Fehler bekommen? Was genau passiert? –

+0

Derzeit erhalte ich das letzte Objekt, das mit EntityManager gelöst wurde, d. H. BusinessManager. – maxspan

+0

Wie erwartet der Contianer, welche konkrete Klasse Sie hier haben möchten? – DavidG

Antwort

2

ich nicht u Verstehen Sie, warum Sie denken, dass Sie in dieser Situation bedingte Abhängigkeitsinjektionen benötigen, weil die Lösung, um es zum Laufen zu bringen, sehr einfach ist.

Sie können Ihre Controller so ändern, dass sie den richtigen Abhängigkeitstyp eingeben, den sie benötigen.

public class PayerController 
{ 
    private PayerManager Manager { get; } 

    public PayerController(PayerManager manager) 
    { 
     Manager = manager; 
    } 
} 

public class BusinessController 
{ 
    private BusinessManager Manager { get; } 

    public BusinessController(BusinessManager manager) 
    { 
     Manager = manager; 
    } 
} 

Stellen Sie dann sicher, dass beide Typen im Servicebehälter registriert sind.

services.AddScoped<PayerManager>(); 
services.AddScoped<BusinessManager>(); 

UPDATE

Eine bessere Möglichkeit ist Schnittstellen zu verwenden und möglicherweise ein abstrakten generischen Controller.

Definieren Sie Ihre Schnittstellen:

public interface IEntityManager { } 
public interface IPayerManager : IEntityManager { } 
public interface IBusinessManager : IEntityManager { } 

Aktualisieren Sie Ihre Klassen, die Schnittstellen zu implementieren:

public abstract class EntityManager : IEntityManager 
{ 
    protected EntityManager() { } 
} 

public class PayerManager : EntityManager, IPayerManager 
{ 
    public PayerManager() : base() { } 
} 

public class BusinessManager : EntityManager, IBusinessManager 
{ 
    public BusinessManager() : base() { } 
} 

Dann eine Basis Controller-Klasse erstellen:

public abstract class EntityController<T> : Controller where T : class, IEntityManager 
{ 
    protected(T manager) 
    { 
     Manager = manager 
    } 

    protected T Manager { get; } 
} 

ändern Controller von erben Basiscontroller:

public class PayerController : EntityController<IPayerManager> 
{ 
    public PayerController(IPayerManager manager) : base(manager) { } 
} 

public class BusinessController : EntityController<IBusinessManager> 
{ 
    public BusinessController(IBusinessManager manager) : base(manager) { } 
} 

und aktualisieren Sie die Service-Register:

services.AddScoped<IPayerManager, PayerManager>(); 
services.AddScoped<IBusinessManager, BusinessManager>(); 
+0

Ich möchte eine abstrakte Klasse oder eine verwenden Schnittstelle keine konkrete Klasse. – maxspan

+1

Erstellen Sie anschließend Schnittstellen für Ihre Verwaltungsklassen, und registrieren Sie diese beim Dienstanbieter. – Brad

+0

Ich habe meine Antwort aktualisiert, um zu zeigen, wie man es mit Schnittstellen und einem generischen Basiscontroller macht – Brad

1

Make-Schnittstelle für jede konkrete Klasse und Einspeisen Schnittstelle in der Steuerung

Startup.cs

services.AddScoped<IPayerManager, PayerManager>(); 
services.AddScoped<IBusinessManager, BusinessManager>(); 

Controller

public class PayerController 
{ 
    private IPayerManager _entityManager{get;} 
    public PayerController(IPayerManager entityManager) 
    { 
     _entityManager= entityManager; 
    } 
} 


public class BusinessController 
{ 
    private IBusinessManager _entityManager{get;} 
    public BusinessController(IBusinessManager entityManager) 
    { 
     _entityManager= entityManager; 
    } 
} 

Manager-Klassen

public class PayerManager : EntityManager,IPayerManager 
{ 
    public void MyPayer() 
    { 
    } 
} 

public class BusinessManager : EntityManager,IBusinessManager 
{ 
    public void MyBusiness() 
    { 
    } 
} 

public abstract class EntityManager 
{ 
    public string IAMCommon() 
    { 
     return ""; 
    } 
} 

Schnittstellen

public interface IPayerManager 
{ 
    void MyPayer(); 
} 

public interface IBusinessManager 
{ 
    void MyBusiness(); 
}