使用 Ninject 在运行时进行依赖注入

Dependency injection at runtime using Ninject

如何使用 Ninject 注入特定的依赖项,而要注入的 class 仅在运行时确定?我有一个界面和实现如下:

public interface ICompanyDAL
{
   Company LoadProfile(int companyID);
}

public class TechCompanySqlDAL : ICompanyDAL
{
    Company LoadProfile(int companyID)
    {
        //Call Stored procs related to TechCompany
        //Populate Model class TechCompany which is derived from abstract class Company
    }
}

public class BankingCompanySqlDAL : ICompanyDAL
{
    Company LoadProfile(int companyID)
    {
        //Call Stored procs related to BankingCompany
        //Populate Model class BankingCompany which is derived from abstract class Company
    }
}

我有一个服务 class 需要调用两个具体 class 之一,如下所示。

public class CompanyService
{
    private readonly ICompanyDAL companyDAL;

    public CompanyHousingService(ICompanyDAL compDAL)
    {
        this.companyDAL = compDAL;
    }

    public Company LoadProfile(int companyID, CompanyType type)
    {
        if(type == CompanyType.Tech)
           //Need to call TechCompanyDAL
        else if (type == CompanyType.Banking)
           //Need to call BankingCompanyDAL
    }   

}

我不希望服务 class 依赖于任何具体的 classes,因为它们可能会改变。我们也可能会添加更多公司类型。那么如何根据反射将ICompanyDAL注入到服务中呢

如果有人解释了更好的替代方案,我也愿意接受有关更改上述模式的建议。

您可以使 ICompanyDAL 通用并将两个依赖项注入 CompanyService,如下所示:

public interface ICompanyDAL<T> where T:Company
{
    T LoadProfile(int companyID);
}

public class TechCompanySqlDAL : ICompanyDAL<TechCompany>
{
    public TechCompany LoadProfile(int companyID)
    {
        //Call Stored procs related to TechCompany
        //Populate Model class TechCompany which is derived from abstract class Company
    }
}

public class BankingCompanySqlDAL : ICompanyDAL<BankingCompany>
{
    public BankingCompany LoadProfile(int companyID)
    {
        //Call Stored procs related to BankingCompany
        //Populate Model class BankingCompany which is derived from abstract class Company
    }
}

public class CompanyService
{
    private readonly ICompanyDAL<BankingCompany> bankingCompanyDAL;
    private readonly ICompanyDAL<TechCompany> techCompanyDAL;

    public CompanyService(ICompanyDAL<BankingCompany> banking_company_dal, ICompanyDAL<TechCompany> tech_company_dal)
    {
        bankingCompanyDAL = banking_company_dal;
        techCompanyDAL = tech_company_dal;
    }

    public Company LoadProfile(int companyID, CompanyType type)
    {
        if (type == CompanyType.Tech)
            return techCompanyDAL.LoadProfile(companyID);
        else if (type == CompanyType.Banking)
            return bankingCompanyDAL.LoadProfile(companyID);

        //handle case of invalid type 
    }   
}

下面是注册依赖项和解析 CompanyService 对象的方法:

StandardKernel kernel = new StandardKernel();

kernel.Bind<ICompanyDAL<TechCompany>>().To<TechCompanySqlDAL>();
kernel.Bind<ICompanyDAL<BankingCompany>>().To<BankingCompanySqlDAL>();

var service = kernel.Get<CompanyService>();

有很多方法可以解决,例如您可以使用 ganerics,但其中之一是:

you can change the ctor dependency to IEnumerable<ICompanyDAL>. so maybe this will works fine to you, see the code below:

public interface ICompanyDAL
{
   CompanyType CompanyType {get;}
   Company LoadProfile(int companyID);
}

public class TechCompanySqlDAL : ICompanyDAL
{
    public CompanyType CompanyType => CompanyType.Tech;
    Company LoadProfile(int companyID)
    {
        //Call Stored procs related to TechCompany
        //Populate Model class TechCompany which is derived from abstract class Company
    }
}

public class BankingCompanySqlDAL : ICompanyDAL
{
    public CompanyType CompanyType => CompanyType.Banking;
    Company LoadProfile(int companyID)
    {
        //Call Stored procs related to BankingCompany
        //Populate Model class BankingCompany which is derived from abstract class Company
    }
}

现在服务:

public class CompanyService
{
    private readonly IEnumerable<ICompanyDAL>compDALs;

    public CompanyHousingService(IEnumerable<ICompanyDAL> compDALs)
    {
        this.companyDALs = compDALs;
    }

    public Company LoadProfile(int companyID, CompanyType type)      
       => companyDALs.FirstOrDefault(s => s.CompanyType==type)?.LoadProfile(companyID); 
}