C# 如果我的ninject引用不在我的web项目上,如何为我的MVC控制器设置ninject绑定?
免责声明:这个问题最初是一个技术问题,但随着时间的推移,它变成了一个没有正确或错误答案的问题。对此我很抱歉。但是,我会礼貌地请您保持开放,以便我们可以一起改进此解决方案 我从一个MVC4项目的Ninject开始。 我在以下项目中设置我的解决方案:C# 如果我的ninject引用不在我的web项目上,如何为我的MVC控制器设置ninject绑定?,c#,ninject,C#,Ninject,免责声明:这个问题最初是一个技术问题,但随着时间的推移,它变成了一个没有正确或错误答案的问题。对此我很抱歉。但是,我会礼貌地请您保持开放,以便我们可以一起改进此解决方案 我从一个MVC4项目的Ninject开始。 我在以下项目中设置我的解决方案: -- Ninject References in both UI and Bootstrapper -- UI ------------> Bootstrapper ----- | |
-- 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。是的,数据访问逻辑将设置在该层中,但我希望能够在不影响业务的情况下更改此逻辑。我更新了我的问题,你觉得我的建议怎么样?我不明白是什么阻止你关闭我所描述的任何功能。每一层应该只依赖于下一层的抽象。。这意味着实际的实现可以随意切换。很抱歉花了这么长时间才返回给您。是的,如果我错了,请更正,但据我所知,如果我的业务层引用