C# 如果我的ninject引用不在我的web项目上,如何为我的MVC控制器设置ninject绑定?

C# 如果我的ninject引用不在我的web项目上,如何为我的MVC控制器设置ninject绑定?,c#,ninject,C#,Ninject,免责声明:这个问题最初是一个技术问题,但随着时间的推移,它变成了一个没有正确或错误答案的问题。对此我很抱歉。但是,我会礼貌地请您保持开放,以便我们可以一起改进此解决方案 我从一个MVC4项目的Ninject开始。 我在以下项目中设置我的解决方案: -- Ninject References in both UI and Bootstrapper -- UI ------------> Bootstrapper ----- | |

免责声明:这个问题最初是一个技术问题,但随着时间的推移,它变成了一个没有正确或错误答案的问题。对此我很抱歉。但是,我会礼貌地请您保持开放,以便我们可以一起改进此解决方案

我从一个MVC4项目的Ninject开始。 我在以下项目中设置我的解决方案:

-- Ninject References in both UI and Bootstrapper --

UI ------------> Bootstrapper -----
 |                    |           |
 |                    |           |
 ˅                    |           |
Business <-------------           |
 |                    |           |
 |                    |           |
 ˅                    ˅           |
Data --------------> Model        |
  ^                               |
  |_______________________________|    
  • 生意
  • 资料
  • 模型
  • 基础架构(ninject引用应该放在哪里)
我的问题是现在我无法解决我的控制器,我有以下问题

绑定:

public class Module : NinjectModule
{
    public override void Load()
    {
        //Bind<IHttpControllerActivator>().To<MyHttpControllerActivator>();
        Bind<ISomething>().To<ConcreteSomething>();
    }
}
Global.asax:

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        Bootstrap.Init();
        AreaRegistration.RegisterAllAreas();

        WebApiConfig.Register(GlobalConfiguration.Configuration);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
    }
}
引导类:

 public class Bootstrap
{
    public static void Init()
    {
        IKernel kernel = new StandardKernel();
        kernel.Load(Assembly.GetExecutingAssembly());
    }
}
这对我来说很好,而且很不耦合。我的问题是,现在我无法使用控制器,我得到消息:

没有为此对象定义无参数构造函数

我读到,我必须将我的MVCAPApplication更改为从NinjectHttpApplication继承而不是从HttpApplication继承,但我不能,因为我没有引用此项目中的Ninject。 我可以为我的控制器设置绑定吗

谢谢

编辑1: 为了实现这一点,我做了以下工作:


我不得不添加这个类

public class NinjectControllerFactory : DefaultControllerFactory
{
    private IKernel ninjectKernel;
    public NinjectControllerFactory(IKernel kernel)
    {
        ninjectKernel = kernel;
    }


    public override IController CreateController(RequestContext requestContext, string controllerName)
    {
        try
        {
            Type controllerType = base.GetControllerType(requestContext, controllerName);
            return ninjectKernel.Get(controllerType) as IController;
        }
        catch (Exception)
        {
            return base.CreateController(requestContext, controllerName);
        }
    }
}
public class NinjectControllerFactory : DefaultControllerFactory
{
    private IKernel ninjectKernel;
    public NinjectControllerFactory(IKernel kernel)
    {
        ninjectKernel = kernel;
    }


    public override IController CreateController(RequestContext requestContext, string controllerName)
    {
        try
        {
            Type controllerType = base.GetControllerType(requestContext, controllerName);
            return ninjectKernel.Get(controllerType) as IController;
        }
        catch (Exception)
        {
            return base.CreateController(requestContext, controllerName);
        }
    }
}
并更改了我的引导类:

public class Bootstrap
{
    public static void Init()
    {
        IKernel kernel = new StandardKernel();
        kernel.Load(Assembly.GetExecutingAssembly());

        ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory(kernel));

    }
}
public class Bootstrap
{
    public static void Init()
    {
        IKernel kernel = new StandardKernel();
        kernel.Load(Assembly.GetExecutingAssembly());

        ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory(kernel));

    }
}
编辑2: 作为评论@Simon答案时提出的问题: 如果我错了,请纠正我,但如果我按照您的建议制定项目架构:

UI ------------> Bootstrapper -----
 |                    |           |
 |                    |           |
 ˅                    |           |
Business <-------------           |
 |                    |           |
 |                    |           |
 ˅                    ˅           |
Data --------------> Model        |
  ^                               |
  |_______________________________|    
UI------>引导程序-----
|                    |           |
|                    |           |
˅                    |           |
商业模式|
^                               |
|_______________________________|    
无论如何,我都会把这个系统绑在一起,这将超越使用国际奥委会的理由

这将是我理想的架构:

UI <------------ Bootstrapper -----
                      |           |
                      |           |
                      |           |
Business <-------------           |
                      |           |
                      |           |
                      ˅           |
Data --------------> Model        |
  ^                               |
  |_______________________________|    
UI引导程序----------->接口
|           |           ^
|           |           |
|           |           |
--商业模式||
|    ^                              |           |
|    |______________________________|           |
|_______________________________________________|
这样,我将解耦接口,并使三个主要层彼此完全解耦。 有一个问题是业务接口和数据接口混合在一起,这是真的。这个问题可以通过组织项目和程序员严格使用来最小化(对于像我这样的小项目就足够了)。对于一个更大的项目,也许在不同的项目中打破这一点可以解决这个问题(但是通过在解决方案中创建大量的项目来带来一个新的问题)

我必须更改UI和引导项目之间引用的方向,以便初始化它


你能告诉我你的想法吗?您在这里看到的优点和缺点是什么?

我不得不添加这个类

public class NinjectControllerFactory : DefaultControllerFactory
{
    private IKernel ninjectKernel;
    public NinjectControllerFactory(IKernel kernel)
    {
        ninjectKernel = kernel;
    }


    public override IController CreateController(RequestContext requestContext, string controllerName)
    {
        try
        {
            Type controllerType = base.GetControllerType(requestContext, controllerName);
            return ninjectKernel.Get(controllerType) as IController;
        }
        catch (Exception)
        {
            return base.CreateController(requestContext, controllerName);
        }
    }
}
public class NinjectControllerFactory : DefaultControllerFactory
{
    private IKernel ninjectKernel;
    public NinjectControllerFactory(IKernel kernel)
    {
        ninjectKernel = kernel;
    }


    public override IController CreateController(RequestContext requestContext, string controllerName)
    {
        try
        {
            Type controllerType = base.GetControllerType(requestContext, controllerName);
            return ninjectKernel.Get(controllerType) as IController;
        }
        catch (Exception)
        {
            return base.CreateController(requestContext, controllerName);
        }
    }
}
并更改了我的引导类:

public class Bootstrap
{
    public static void Init()
    {
        IKernel kernel = new StandardKernel();
        kernel.Load(Assembly.GetExecutingAssembly());

        ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory(kernel));

    }
}
public class Bootstrap
{
    public static void Init()
    {
        IKernel kernel = new StandardKernel();
        kernel.Load(Assembly.GetExecutingAssembly());

        ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory(kernel));

    }
}
不,没有

通常,您的UI必须知道它用于引导的内容。这并不意味着您需要引导UI中的所有内容。。。但是您的UI项目需要知道发生了什么(这都是假设我正确理解了您的问题)

因此,您可以这样做:

1) 在UI项目中引用Ninject。这是必须的。它需要能够解析
NinjectHttpApplication

2) 在Global.asax.cs中进行此类设置:

private readonly IKernel _kernel;

public IKernel CreateKernel() { // Ninject calls this after inheriting
                                // from NinjectHttpApplication
    _kernel = Bootstrap.Init();

    return _kernel;
}
3) 更改
Bootstrap.Init
以返回
IKernel

public class Bootstrap {
    public IKernel Init() {
        return new StandardKernel(new NinjectModule[] {
            new YourModule(),
            new YourOtherModule()
        });
    }
}
4) 这使您的依赖流有点像这样:

-- Ninject References in both UI and Bootstrapper --

UI ------------> Bootstrapper -----
 |                    |           |
 |                    |           |
 ˅                    |           |
Business <-------------           |
 |                    |           |
 |                    |           |
 ˅                    ˅           |
Data --------------> Model        |
  ^                               |
  |_______________________________|    
——UI和引导程序中的Ninject引用--
用户界面------->引导程序-----
|                    |           |
|                    |           |
˅                    |           |
商业模式|
^                               |
|_______________________________|    
因此,您的UI引用引导程序和业务项目。引导程序引用所有内容,以便您可以很好地设置绑定。基本上,引导者是一把伞。。它知道一切,所以它可以约束一切。不过,您会注意到,其余的项目都指向下方。您在问题中提出的建议将导致循环引用


此外,根据将域对象映射到ViewModels的位置,UI可能还需要引用模型项目。这很好。

你觉得我的答案怎么样?这将使我的UI独立于nInject。我不理解UI引用业务和业务引用数据。在这里使用国际奥委会有什么好处?他们将被捆绑在一起。我将用我的架构建议更新我的问题。在你的答案中,你的UI仍然与Ninject绑定。您正在设置控制器工厂。。仅在UI中可用。而且,瀑布依赖关系与它们应该的完全一样。我不确定如何设置数据层,但通常数据访问逻辑(如存储库或CQRS设置)驻留在该层中。业务层需要能够调用它来持久化。控制器工厂将设置在我的bootstraper/infrastructure项目中,因此UI将不会绑定到nInject。是的,数据访问逻辑将设置在该层中,但我希望能够在不影响业务的情况下更改此逻辑。我更新了我的问题,你觉得我的建议怎么样?我不明白是什么阻止你关闭我所描述的任何功能。每一层应该只依赖于下一层的抽象。。这意味着实际的实现可以随意切换。很抱歉花了这么长时间才返回给您。是的,如果我错了,请更正,但据我所知,如果我的业务层引用