简体   繁体   中英

Conditional Dependency Resolving in Asp.net core

I am having a 2 controller PayerController and BusinessController. Both Controller constructors takes EntityManager as a parameter which is an abstract class. I would like to resolve Each Manager class depending on the controller I am using.

For PayerController I would like to inject PayerManager class and for BusinessController I would like to inject BusinessManager.

Currentlly I am getting the last Object that has been resolved with EntityManager ie BusinessManager.

I remember in Ninject we can do conditional injection pretty easily.

This is how current I am resolving the dependency But wont work.

Startup.cs

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

Controllers

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

Manager Classes

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

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

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

I don't understand why you think you need conditional dependency injection in this situation because the solution to make it work is very simple.

You can change your controllers to inject the correct type of dependency that they need.

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

Then make sure both types are registered in the service container.

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

UPDATE

A better way is to use interfaces and possibly an abstract generic controller.

Define your interfaces:

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

Update your classes to implement the interfaces:

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

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

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

Then create a base controller class:

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

    protected T Manager { get; }
}

Change your controllers to inherit from base controller:

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

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

And update the service register:

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

Make interface for each concrete class and Injecting interface in the controller

Startup.cs

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

Controllers

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 Classes

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

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

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

Interfaces

public interface IPayerManager
{
    void MyPayer();
}

public interface IBusinessManager
{
    void MyBusiness();
}

@Maxspan, my suggestion:

Put all interfaces in Contracts folder and this folder inside your Models/Entities folder (Models/Entities folder - Contracts folder)

IEntityManager Interface

namespace WebApplication1.Entities.Contracts
{
    public interface IEntityManager
    {
        //Method signature only
        string IAMCommon();
    }
}

IBusinessManager Interface

namespace WebApplication1.Entities.Contracts
{
    public interface IBusinessManager : IEntityManager
    {
        //Method signature only
        void MyBusiness();
    }
}

IPayerManager Interface

namespace WebApplication1.Entities.Contracts
{
    public interface IPayerManager : IEntityManager
    {
        //Method signature only
        void MyPayer();
    }
}

BusinessManager Concrete Class

using System;
using WebApplication1.Entities.Contracts;

namespace WebApplication1.Entities
{
    public class BusinessManager : IBusinessManager
    {
        //Method signature in IEntityManager
        public string IAMCommon()  //Heritage in IBusinessManager (IBusinessManager : IEntityManager)
        {
            //Implement your code here.
            throw new NotImplementedException();
        }

        //Method signature in IBusinessManager
        public void MyBusiness() 
        {
            //Implement your code here.
            throw new NotImplementedException();
        }
    }
}

PayerManager Concrete Class

using System;
using WebApplication1.Entities.Contracts;

namespace WebApplication1.Entities
{
    public class PayerManager : IPayerManager
    {
        //Method signature in IEntityManager
        public string IAMCommon() //Heritage in IPayerManager (IPayerManager : IEntityManager)
        {
            //Implement your code here.
            throw new NotImplementedException();
        }

        //Method signature in IPayerManager
        public void MyPayer()
        {
            //Implement your code here.
            throw new NotImplementedException();
        }
    }
}

Startup class

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using WebApplication1.Entities;
using WebApplication1.Entities.Contracts;

namespace WebApplication1
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddScoped<IBusinessManager, BusinessManager>();
            services.AddScoped<IPayerManager, PayerManager>();
        }
    }
}

BusinessController

using Microsoft.AspNetCore.Mvc;
using WebApplication1.Entities.Contracts;

namespace WebApplication1.Controllers
{
    public class BusinessController : Controller
    {
        private readonly IBusinessManager _businessManager;

        public BusinessController(IBusinessManager businessManager)
        {
            _businessManager = businessManager;
        }

        public IActionResult Index()
        {
            //Both methods in BusinessManager due to heritage (BusinessManager : IBusinessManager)
            _businessManager.IAMCommon(); 
            _businessManager.MyBusiness();

            return View();
        }
    }
}

PayerController

using Microsoft.AspNetCore.Mvc;
using WebApplication1.Entities.Contracts;

namespace WebApplication1.Controllers
{
    public class PayerController : Controller
    {
        private readonly IPayerManager _payerManager;

        public PayerController(IPayerManager payerManager)
        {
            _payerManager = payerManager;
        }

        public IActionResult Index()
        {
            //Both methods in PayerManager due to heritage (PayerManager : IPayerManager)
            _payerManager.IAMCommon(); 
            _payerManager.MyPayer(); 

            return View();
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM