C# n层应用程序中的Ninject

C# n层应用程序中的Ninject,c#,ninject,C#,Ninject,虽然DI和IoC容器的概念相当直截了当,但我似乎正在努力实现。我有一个四层应用程序,UI层to服务层使用了IoC,似乎工作得很好,但是服务层to业务层是一个绝对的痛苦 我读过很多文章,特别是Ninject和类库,但我仍然无法正确实现。我希望你们这些善良的人能给我指出正确的方向 典型的分层流程:UI层>服务层>业务层>数据层 因此,如果可以将myUI层的实现显示到服务层: private static void RegisterServices(IKernel kernel) {

虽然
DI
IoC容器
的概念相当直截了当,但我似乎正在努力实现。我有一个四层应用程序,
UI层
to
服务层
使用了
IoC
,似乎工作得很好,但是
服务层
to
业务层
是一个绝对的痛苦

我读过很多文章,特别是
Ninject
类库
,但我仍然无法正确实现。我希望你们这些善良的人能给我指出正确的方向

典型的分层流程:UI层>服务层>业务层>数据层

因此,如果可以将my
UI层
的实现显示到
服务层

    private static void RegisterServices(IKernel kernel)
    {
        kernel.Bind<IApiAuthorizationService>().To<ApiAuthorizationService>();
    } 

    public class DebateController : ApiController
    {
        private IApiAuthorizationService _iApiAuthorizationService;
        public DebateController(IApiAuthorizationService iApiAuthorizationService)
        {
            _iApiAuthorizationService = iApiAuthorizationService;
        }
     }
此时,我已经在
服务层上安装了Ninject,并且还创建了一个类来创建绑定:

public class Bindings : NinjectModule
{
    public override void Load()
    {
        Bind<IApiAuthTokenRepository>().To<ApiAuthTokenRepository>();
    }
}
公共类绑定:NinjectModule
{
公共覆盖无效负载()
{
绑定()到();
}
}
基本上,我被困在这一点上,不知道该去哪里,我也读了很多文章,但很多人使用
控制台应用程序来演示,
类库没有入口点。我当时的想法是添加一个
Startup.cs
来初始化绑定

有没有人能用一些演示代码给我指出正确的方向


谢谢。

您可以做您正在做的事情,并创建一个注册服务的位置。那就行了。但是,如果您认为应用程序有好处,这里有一种高级方法也可以使用

总体思路是在依赖项注入库和应用程序之间建立一个层。我们把这层称为IServiceContainer

public class ServiceContainer : IServiceContainer
{
  // internally manages ninjects kernel via methods such as...
  public void RegisterType<TService, TInstance>();
  public void RegisterTypes(Assembly assembly);

  // ultimately, this just segregates Ninject from your app so there are no Ninject dependencies
}
IServiceContainer.RegisterTypes的实现将扫描其中的所有类型以查找ServiceRegistrationAttribute。现在,您可以通过IServiceContainer.RegisterType()自动注册每种类型的服务类型和实现类型

这可以根据需要进行,也可以不进行

至于这如何解决“在N层应用程序中使用”的问题。。。 您可以在每个程序集中提供一个接口实现,该实现知道如何注册它的所有需求,并且该实现可能反过来从它所依赖的另一个程序集中调用相同的接口实现。通过这种方式,您可以允许每个程序集沿着其从属程序集的注册前进。这是一个长期战略,可能会给你一些有用的想法

这里是一个大概的想法,它可能看起来像什么(记住,你会在每个组件中有一个)

公共类自动注册:IAutoRegistration
{
公共无效寄存器(IServiceContainer容器)
{
//其中,添加的类型为IAutoRegistration
container.Add();
container.Add();
}
}
IServiceContainer只需收集添加的所有不同IAutorRegistration(它从.Add()中的每个TautoreRegistration中知道该点的程序集),并可以扫描属性的类型(如前所示),然后逐个注册类型。

主要用于实例化DI容器并对其进行配置的位置应该是应用程序入口点。这意味着您永远不会在库中实例化DI容器。也意味着入口点需要知道所有依赖项并相应地配置它们。 MarkSeeman有一篇关于原则的博客文章:

“足够好”的方法 现在,在大多数项目中,我在某种程度上违反了这种方法——这有优点也有缺点。 Ninject(和Autofac…)具有模块的概念。模块是一组绑定/注册,因此它是一个(部分)容器配置规范。这些可以添加到库中并在合成根目录中获取。 这一概念被记录在案

例如:

  • WpfApplication.exe
    • 包含一组
      ninject模块
      s
    • 表示复合根目录,其内容大致如下:
      var kernel=new StandardKernel()
      kernel.Load(AppDomain.CurrentDomain.GetAssemblies();
  • ServiceLayer.dll
    • 包含一组
      ninject模块
      s
  • BusinessLayer.dll
    • 包含一组
      ninject模块
      s
  • DataLayer.dll
    • 包含一组
      ninject模块
      s
你什么时候不应该这样做

  • 当这些*.dll中的任何一个应该在多个项目/软件中使用时,根据项目的不同,您可能需要不同的绑定(容器配置)。这通常不能重用(另请参阅)
  • 当您计划频繁地更改容器时,这将带来更多的工作

在这些情况下,您应该严格遵守Mark的合成根概念。

您在哪里初始化容器?您能显示代码吗?@YacoubMassad再次向服务提供UI很好…这是服务对业务,我目前不确定。我不初始化容器,因为这是问题…在类库中在哪里这样做。哟你不应该在类库中使用容器。你应该只在.Related:@Steven thank You+1中使用它。它确实有助于澄清一些问题。感谢你提供了非常翔实的答案。我仍然对这种方法感到好奇和不确定。我不确定现在在哪里看到这段代码:var kernel=new StandardKernel();Register(kernel);//注册objects var apiAuthTokenRepository=kernel.Get();//创建实例这些功能已经包含在许多DI容器中,包括Ninject-无需“自己滚动”。此外,这里还有一些关于“公共抽象”的想法:非常好的答案,有
public class ServiceContainer : IServiceContainer
{
  // internally manages ninjects kernel via methods such as...
  public void RegisterType<TService, TInstance>();
  public void RegisterTypes(Assembly assembly);

  // ultimately, this just segregates Ninject from your app so there are no Ninject dependencies
}
[ServiceRegistration(typeof(IApiAuthorizationService))]
public class ApiAuthorizationService : IApiAuthorizationService
{
    private IApiAuthTokenRepository _iApiAuthTokenRepository;
    public ApiAuthorizationService(IApiAuthTokenRepository iApiAuthTokenRepository)
    {
        _iApiAuthTokenRepository = iApiAuthTokenRepository;
    }
}
public class AutoRegistration: IAutoRegistration
{
    public void Register(IServiceContainer container)
    {
        // where the type of Add<> is IAutoRegistration
        container.Add<SomeDependentNamespace.AutoRegistration>();
        container.Add<SomeOtherDependentNamespace.AutoRegistration>();
    }
}