在标准应用程序中注入自定义代码

时间:2013-03-18 16:57:21

标签: c# ninject unity-container

我们公司有一个标准的应用程序。 现在我想在应用程序中注入一些自定义程序集。

通常,如果你有一个ninject内核或统一容器,你可以得到如下所示的实现:

IKernel kernel = new StandardKernel();
DealerService myServ = new DealerService(kernel.Get<IDealerController>());

DealerService:

public partial class DealerService : ServiceBase
{
    private readonly IDealerController Controller;

    public DealerService(IDealerController controller)
    {
        Controller = controller;

        InitializeComponent();
    }

    protected override void OnStart(string[] args)
    {
        Process();
    }

    protected override void OnStop()
    {
    }

    public void Process()
    {
        Controller.GetDealerDetails(5);
    }
}

DealerController接口

public interface IDealerController
{
    Dealer GetDealerDetails(int dealerId);
}

经销商控制器的实施:

public class DealerController : IDealerController
{
    public Dealer GetDealerDetails(int dealerId)
    {     
        throw new NotImplementedException("This is a custom error thrown from the controller implementation");
    }
}

现在问题是我不希望标准应用程序知道自定义程序集。 dealerervice是一个工作流活动,因此可以通过工作流基础动态找到。问题是注入的DealerController是空的...... 如何在没有第IDealerController行的标准应用程序中注入kernel.Get<IDealerController>()的实现。

如果将Ninject与ninject MVC 3 nuget包一起使用,则实现将注入mvc控制器的构造函数中,而不调用kernel.Get<IDealerController>()

修改 添加了模块作为程序集名称Ninject.Extensions.Controllers.Module,以便通过命名约定找到模块。这在Ninject documentation中有所描述。这适用于我的MVC应用程序。

public class ControllersModule : NinjectModule
{
    public override void Load()
    {            
        this.Bind<IDealerController>().To<DealerController>();            
    }
}

2 个答案:

答案 0 :(得分:1)

如果您想将IDealerController实施注入DealerService,您还必须让Ninject管理DealerService的实例化。

IKernel kernel = new StandardKernel();
kernel.Bind<IDealerController>.To<DefaultDealerController>(); //.InSingletonScope();
kernel.Bind<DealerService>().ToSelf(); //.InSingletonScope();
DealerService myServ = kernel.Get<DealerService>();

要动态加载Ninject配置,您可以使用modules方法和kernel.Load("*.dll")方法。如果您将有多个接口的多个实现,您还应该在conditional binding的帮助下指定应该使用哪个接口。

kernel.Bind<IDealerController>
      .To<SpecialDealerController>()
      .When(x=> SpecialConditionIsMet());

答案 1 :(得分:0)

您可以在每个程序集中继承Module的不同NinjectModule

public class WarriorModule : NinjectModule
{
    public override void Load() 
    {
        Bind<IWeapon>().To<Sword>();
        Bind<Samurai>().ToSelf().InSingletonScope();
    }
}

然后使用Kernel动态加载AppDomain中所有程序集中的所有模块:

kernel.Load(AppDomain.CurrentDomain.GetAssemblies());

所有示例均来自Ninject documentation