我正在计划一些工作,将依赖注入引入当前的大型单片库,试图使库更容易进行单元测试,更容易理解,并可能更灵活地作为奖励.
我决定使用NInject,我真的很喜欢Nate的"做一件事,做得好"(转述)的座右铭,而且它似乎在DI的背景下特别好.
我现在想知道的是,我是否应该将当前单个大型装配拆分为具有不相交特征集的多个较小装配.这些较小的程序集中的一些将具有相互依赖性,但远非所有这些程序集,因为代码的体系结构已经非常松散地耦合.
请注意,这些功能集不是微不足道的,也不是很小......它包含客户端/服务器通信,序列化,自定义集合类型,文件IO抽象,常用例程库,线程库,标准日志记录等.
我看到前一个问题:什么是更好的,许多小型装配,或一个大装配?有点解决这个问题,但是看起来更精细的粒度,这让我想知道那里的答案是否仍适用于这种情况?
此外,在接近这个主题的各种问题中,一个常见的答案是,"太多"集会导致了未指明的"痛苦"和"问题".我真的想要具体了解这种方法可能存在的缺点.
我同意在仅需要1个之前添加8个组件是"有点痛苦",但是必须为每个应用程序包含一个大的单片库也不是完全理想的...加上8个组件只是你做的事情曾经,所以我对这个论点很少有同情心(即使我最初可能会和其他人一起抱怨).
附录:
到目前为止,我已经看到没有针对小型装配的任何理由,所以我想我现在将继续进行,好像这是一个非问题.如果有人能够用可验证的事实来考虑好的可靠理由来支持它们,我仍然会非常有兴趣了解它们.(我会尽快增加赏金以提高知名度)
编辑:将性能分析和结果移到单独的答案中(见下文).
我有一个具有几个不同具体实现的接口.我试图给Ninject一个默认使用,如果名称匹配,只使用其他实现.例如,我有以下绑定.
Bind<ISomething>().To<DefaultSomething>()
Bind<ISomething>().To<OtherSomething>().Named("55abd8b8-097f-4e1c-8d32-95cc97910604");
Run Code Online (Sandbox Code Playgroud)
我想要的是,如果命名部分不匹配,使用DefaultSomething实现.当我传入明确绑定的guid时,它工作正常.当我传入任何其他guid时,我得到"没有匹配的绑定可用"异常.
Bind<ISomething>().To<OtherSomething>().Named("55abd8b8-097f-4e1c-8d32-95cc97910604");
Bind<ISomething>().To<DefaultSomething>()
Bind<ISomething>().To<DefaultSomething>()
Bind<ISomething>().To<OtherSomething>().When(ctx => ctx.Service != null && ctx.Service.Name == "55abd8b8-097f-4e1c-8d32-95cc97910604");
Run Code Online (Sandbox Code Playgroud)
我也尝试过使用.当检查绑定时,我尝试颠倒了下面的顺序但是我永远无法绑定,除非我传入明确命名的Guid.
这篇文章似乎表明默认绑定有效,所以我一定做错了.有什么建议?
编辑:这是一个完整的例子,显示我想解决的问题.期望的行为是kernel.Get<INumber>("Three").Write()返回"Unknown Number"
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Ninject;
namespace NinjectTest
{
interface INumber
{
string Write();
}
class UnknownNumber : INumber
{
public string Write()
{
return "Unknown Number";
}
}
class One : INumber
{
public string Write()
{
return "1 = One";
}
}
class Two : INumber
{
public string Write() …Run Code Online (Sandbox Code Playgroud) 我有启用/禁用功能的全局标志.我想根据一些标志注入一些依赖项.某些功能需要构造较多的类,因此如果标志的值为false,则我想注入null,否则需要实际的依赖项.Ninject不允许注入null.还有其他选择吗?
更新:构造函数参数可以使用OptionalAttribute属性进行修饰.在这种情况下,如果没有找到相应的绑定,则注入null.这里有一个问题:我无法验证目标类是否可以正确构造.我对每个公共依赖项进行了测试,验证它是否可以成功构建.如果标志的值为true,我将无法在使用该OptionalAttribute属性修饰的依赖项时找到错误,无法正确构造.我只想在绑定级别上管理它.
请原谅我的无知,但我对IOC和NinJect很新.我已经搜索了高低的易于理解的解决方案,但到目前为止他们已经找不到我了.
到目前为止,我有以下所有工作正如预期:
private class StandardModule : NinjectModule
{
public override void Load()
{
Bind<ILog>().To<NLogLogger>(); // Use NLog
Bind<IMyEntityFrameWorkRepository().To<MyEntityFrameWorkRepository>();
}
}
Run Code Online (Sandbox Code Playgroud)
然后,MyEntityFrameWorkRepository通过app/web.config中声明的连接字符串创建自己的EF DbContext:
public class MyDbContext : DbContext
{
public MyDbContext() : base("MyAppConfig")
{
}
........
}
Run Code Online (Sandbox Code Playgroud)
然而!!我的目标是这样的 - 我意识到这种语法是"胡说八道"(我想我也可能需要IOC MyDbConext),但我希望"伪代码"传达我的愿望:
private class StandardModule : NinjectModule
{
public override void Load()
{
Bind<ILog>().To<NLogLogger>(); // Use NLog
string mySqlConnectionString = MyApp.GetCommandLineArgument("sqlconn"); // "Data Source=..."
Bind<IMyEntityFrameWorkRepository().To<MyEntityFrameWorkRepository>(mySqlConnectionString);
}
}
.................
public class MyDbContext : DbContext
{
public MyDbContext( string sqlConnectionString) :
base(sqlConnectionString) …Run Code Online (Sandbox Code Playgroud) 我有一个项目,其中Ninject用作IoC容器.我担心的是很多类都有这样的构造函数:
[Inject]
public HomeController(
UserManager userManager, RoleManager roleManager, BlahblahManager blahblahManager) {
_userManager = userManager;
_roleManager = roleManager;
_blahblahManager = blahblahManager;
}
Run Code Online (Sandbox Code Playgroud)
如果我不想同时拥有这些类的所有实例,该怎么办?
当所有这些类被包装Lazy<T>并传递给构造函数的方式并不是我所需要的.该T实例尚未创建,但Lazy<T>情况已存储在内存中.
我的同事建议我使用Factory模式控制所有实例,但我不确定IoC是否有这么好的设计错误.
有没有针对这种情况的解决方法,或者IoC在它的设计中确实存在如此大的缺陷?也许我应该使用另一个IoC容器?
有什么建议?
在MVC中,我只是创建NinjectControllerFactory实现DefaultControllerFactory接口的类,然后在其中执行一些绑定.最后在Global我运行它:
ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());
Run Code Online (Sandbox Code Playgroud)
但是在ASP.NET Web API中使用Ninject呢?网上有一些信息,但已过时和预发布版本.
这个问题有直接的方法吗?
我真的想将SharpRepository与Ninject一起使用,但我不明白如何配置Ninject以在存储库之间共享Entity Framework DbContext.
我正在使用Entity Framework版本5和Ninject版本3.
目前我Ef5Repository在我的源代码中使用,但我想用它替换它ConfigurationBasedRepository.但我无法弄清楚如何将EF传递(或注入)DbContext到存储库.
示例(当前状态):
using SharpRepository.Repository;
public interface IProductRepository : IRepository<Product>
{
}
using SharpRepository.Ef5Repository;
using System.Data.Entity;
// TODO Tightly coupled to Ef5Repository.
public class ProductRepository : Ef5Repository<Product>, IProductRepository
{
// TODO The DbContext has to be injected manually.
public ProductRepository(DbContext context) : base(context)
{
}
// [...]
}
Run Code Online (Sandbox Code Playgroud)
目标:
using SharpRepository.Repository;
public interface IProductRepository : IRepository<Product>
{
}
public class ProductRepository : ConfigurationBasedRepository<Product, int>, IProductRepository
{ …Run Code Online (Sandbox Code Playgroud) 我正在Visual Studio 2017版本15.4上开发一个MVC5项目.我在这里得到了意想不到的结果,这是我以前从未遇到的.我已经安装了Ninject.MVC5包nuget.它安装得很好,没有任何错误或警告.但问题是它没有NinjectWebCommon.cs在App_Start文件夹中生成文件.有什么缘故吗?
对于DI和ninject来说,我是一个新手,我正在努力解决实际注入何时发生以及如何开始绑定的问题.
我已经在我的Web应用程序中使用它并且它在那里工作正常,但现在我想在类库中使用注入.
说我有这样一个类:
public class TestClass
{
[Inject]
public IRoleRepository RoleRepository { get; set; }
[Inject]
public ISiteRepository SiteRepository { get; set; }
[Inject]
public IUserRepository UserRepository { get; set; }
private readonly string _fileName;
public TestClass(string fileName)
{
_fileName = fileName;
}
public void ImportData()
{
var user = UserRepository.GetByUserName("myname");
var role = RoleRepository.GetByRoleName("myname");
var site = SiteRepository.GetByID(15);
// Use file etc
}
}
Run Code Online (Sandbox Code Playgroud)
我想在这里使用属性注入,因为我需要在构造函数中传入一个文件名.我是否正确说,如果我需要传入一个构造函数参数,我不能使用构造函数注入?如果我可以使用带有附加参数的构造函数注入,我该如何传递这些参数?
我有一个由Test类使用的控制台应用程序,如下所示:
class Program
{
static void Main(string[] args)
{
// NinjectRepositoryModule Binds my IRoleRepository …Run Code Online (Sandbox Code Playgroud) 注意:现在我输入了这个,我不得不为超长问题道歉,但是,我认为这里提供的所有代码和信息在某种程度上都是相关的.
好吧,我在ASP.NET webforms应用程序的随机点上得到奇怪的"Session Is Closed"错误.然而,今天,它终于在同一个地方一次又一次地发生.我几乎可以确定在我的代码中没有任何处理或关闭会话,因为使用的代码位远离所有其他代码,如下所示.
我也使用ninject作为我的IOC,这可能/可能不重要.
好的,首先,我SessionFactoryProvider和SessionProvider班级:
SessionFactoryProvider
public class SessionFactoryProvider : IDisposable
{
ISessionFactory sessionFactory;
public ISessionFactory GetSessionFactory()
{
if (sessionFactory == null)
sessionFactory =
Fluently.Configure()
.Database(
MsSqlConfiguration.MsSql2005.ConnectionString(p =>
p.FromConnectionStringWithKey("QoiSqlConnection")))
.Mappings(m =>
m.FluentMappings.AddFromAssemblyOf<JobMapping>())
.BuildSessionFactory();
return sessionFactory;
}
public void Dispose()
{
if (sessionFactory != null)
sessionFactory.Dispose();
}
}
Run Code Online (Sandbox Code Playgroud)
SessionProvider
public class SessionProvider : IDisposable
{
ISessionFactory sessionFactory;
ISession session;
public SessionProvider(SessionFactoryProvider sessionFactoryProvider)
{
this.sessionFactory = sessionFactoryProvider.GetSessionFactory();
}
public ISession GetCurrentSession()
{
if (session == null) …Run Code Online (Sandbox Code Playgroud)