我正在尝试使用Ninject.MockingKernel.Moq.我有两个问题:
示例代码:
//Arrange
var kernel = new Ninject.MockingKernel.Moq.MoqMockingKernel();
kernel.Bind<ClassUnderTest>().ToSelf();
kernel.Bind<ILogger>().ToMock();
kernel.GetBindings(typeof(ILogger));
//Act
var sut = kernel.Get<ClassUnderTest>();
sut.DoSomething();//Logger.Log is called inside that method
//Assert
var mock = kernel.GetMock<ILogger>();
mock.Verify(x => x.Log(It.IsAny<string>()), Times.Exactly(1));
Run Code Online (Sandbox Code Playgroud) 代码示例:
namespace DependencyInjection
{
class Program
{
static void Main(string[] args)
{
IKernel kernel = new StandardKernel();
var samurai = kernel.Get<Samurai>();
Bind<IWeapon>().To<Sword>();
}
}
class Samurai
{
readonly IWeapon _weapon;
public Samurai(IWeapon weapon)
{
_weapon = weapon;
}
public void Attack(string target)
{
_weapon.Hit(target);
}
}
interface IWeapon
{
void Hit(string target);
}
class Sword : IWeapon
{
public void Hit(string target)
{
Console.WriteLine("Sword - ", target);
}
}
class Arrow : IWeapon
{
public void Hit(string target)
{
Console.WriteLine("Arrow …Run Code Online (Sandbox Code Playgroud) 我已经阅读了许多有关在开发中使用IoC容器的有趣文章.在许多情况下,作者建议我们编写自己的简单包装器,它隐藏了读取容器的接口,如Ninject,Castle.Windsor,Unity等.
包装器的实现看起来像这样(对于Ninject):
/// <summary>
/// Contains links for service contract and realization.
/// </summary>
public static class IoC
{
static readonly IKernel kernel;
static IoC()
{
kernel = new StandardKernel();
}
public static void RegisterService<T>(Type service)
{
kernel.Bind<T>().To(service);
}
public static T Resolve<T>()
{
return kernel.Get<T>();
}
}
Run Code Online (Sandbox Code Playgroud)
好的,但是如何使用此模式的高级功能?例如,我喜欢使用像InRequestScope()或InSingletonScope()这样的生命周期管理修饰符,许多容器都支持这种修饰符.使用上面的模式,我可以丢弃ninject并使用15行实现.区别在哪里?
我还看了一下CommonServiceLocator试图找到丰富的包装器,但它与我的IoC类没有太大区别.现在我认为我不应该制作自己的自行车并直接使用全功能容器.你呢?
我的申请包括三个项目.核心,DAL和BAL.
核心包含域对象(客户,订单,产品).它还包含基本的IRepository接口IRepository<T>.
DAL包含EntityFramework特定的东西.它还包含Concrete Repositories(CustomerRepository,OrderRepository,ProductRepository).我在这里添加了这些具体的存储库,因为它们依赖于DbContext(这是EF特定的)
现在我的BAL应该只依赖于Core而不依赖于DAL.我在这个项目中添加了对NInject的依赖.但是,我仍然需要告诉Ninject它应该将IRepository解析<Customer>为CustomerRepository,这迫使我在这里添加DAL依赖.无论如何避免在我的BAL项目中添加对DAL的依赖?
我怎么能用Ninject做到这一点
var lst=new List<IAnimal>();
lst.Add(dog);
lst.Add(cat);
kernel.Bind<List<IAnimal>>().ToInstance(lst);
Run Code Online (Sandbox Code Playgroud)
我应该使用什么而不是ToInstance()作为Ninject没有这种方法?
TL; DR:Kernel.Get<T>工作从.NET/WPF应用程序调用时,但与内鼓起ActivationException(内侧TargetInvocationException)从VB6应用程序调用时.WTH?
这是对这个问题的一个跟进,在那里我使用Ninject约定配置了一个抽象工厂,这样我就不需要实际实现一个,Ninject工厂扩展负责生成一个动态.
这很好用......直到我需要从VB6代码运行我的库.
_kernel.Bind(t => t.FromAssemblyContaining(typeof(ViewModelBase))
.SelectAllInterfaces()
.EndingWith("ViewFactory")
.BindToFactory());
Run Code Online (Sandbox Code Playgroud)
一旦我从VB6代码中调用应用程序上的任何内容,如果我将依赖项的解析包装在try/catch块中,那么我将TargetInvocationException使用内部函数捕获一个ActivationException:
使用IInterceptor Provider的条件隐式自绑定激活IInterceptor时出错返回null.激活路径:
3)将依赖性IInterceptor注入到IViewFactoryProxy类型的构造函数的参数中
2)将依赖IViewFactory注入到MsgBox类型的构造函数的参数viewFactory中
1)请求IMsgBox
建议:
1)确保提供程序正确处理创建请求.
我没有引用Ninject.Interception扩展(此时).
奇怪的是,如果不是启动VB6,我在调试时启动沙盒WPF测试应用程序,我没有得到任何ActivationException东西,一切都像魅力一样.
VB6代码死了automation error -2146232828 (80131604),谷歌没有产生任何东西,但我猜它与TargetInvocationException抛出的东西有关.
就.net代码而言,它只是起作用:如果我从WPF客户端编写应用程序,我可以在MsgBox类构造函数中打破并看到IViewFactory参数对a满意Castle.Proxy.IViewFactoryProxy; 如果我从VB6 ActiveX DLL中编写应用程序(我还创建了一个VB6 EXE来测试和DLL一样),它会爆炸.
我删除了通用抽象工厂,我不再收到此错误.而且因为我不想写工厂,所以我选择了一些我可以忍受的更紧密的耦合.现在我想知道为什么会这样!
尝试使用ninject将泛型参数传递给装饰器链时遇到了问题.也许最好用代码解释一下:
public interface IConnector
{
void Connect();
}
public class CoreConnector : IConnector
{
public void Connect()
{
Console.WriteLine("core connector");
}
}
public class LoggingConnector : IConnector
{
private readonly IConnector conn;
private string id;
public LoggingConnector(IConnector conn, string id)
{
this.conn = conn;
this.id = id;
}
public void Connect()
{
Console.WriteLine("logging conn id : {0}",id);
conn.Connect();
}
}
public class AuditingConnector : IConnector
{
private readonly IConnector conn;
private string id;
public AuditingConnector(IConnector conn, string id)
{
this.conn …Run Code Online (Sandbox Code Playgroud) 我正在构建一个ASP.NET MVC5 Web应用程序,使用Ninject.MVC5进行DI.我正在尝试将NinjectWebCommon类移动到一个单独的类库项目中.我能够通过使用以下代码成功完成此操作:
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
try
{
// Uncomment to move this file to a separate DLL
kernel.Load("MyWebApp.dll");
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
return kernel;
}
catch
{
kernel.Dispose();
throw;
}
}
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,MyWebApp.dll是主Web应用程序程序集的文件名.这有效,但要求我硬编码对Web应用程序DLL的引用.我在官方文档中读到,以下内容可以用于自动加载以这种方式分离的解决方案中的所有 DLL:
kernel.Load(AppDomain.CurrentDomain.GetAssemblies());
Run Code Online (Sandbox Code Playgroud)
但是,如果我使用此代码而不是硬编码引用,我会收到以下异常(在throw上面的行中捕获并重新抛出):
An exception of type 'System.NotSupportedException' occurred in
MyWebApp.Infrastructure.dll and wasn't handled before a managed/native boundary
Additional information: Error loading module 'Ninject.Web.Mvc.MvcModule' of
type MvcModule
Run Code Online (Sandbox Code Playgroud)
任何人都可以提供有关此处发生的事情的一些信息,以及如何在避免对其他程序集进行硬编码引用的同时防止发生此异常?
在我的NinjectConfigurator中
container.Bind<IClock>().To<SystemClock>();
Run Code Online (Sandbox Code Playgroud)
我也试过了
container.Bind<IClock>().To<SystemClock>().InSingletonScope();
Run Code Online (Sandbox Code Playgroud)
但我得到这个错误:
错误激活
IClock使用结合IClock到SystemClock没有构造函数可用来创建实现类型的实例.激活路径:3)将依赖IClock注入SystemManager类型构造函数的参数时钟2)将依赖ISystemManager注入到AccountController类型构造函数的参数systemManager中1)对AccountController的请求
建议:1)确保实现类型具有公共构造函数.2)如果已实现Singleton模式,请使用与InSingletonScope()的绑定.
这是我的注入类,与我在项目中使用IoC的所有其他工作类相同:
private readonly IDateTime _dateTime;
private readonly IClock _clock;
public SystemManager(IDateTime dateTime, IClock clock)
{
this._dateTime = dateTime;
this._clock = clock;
}
Run Code Online (Sandbox Code Playgroud)
我找不到任何可以帮助我的事情.任何帮助深表感谢.
正如标题所说,我正在编写集成测试,并希望测试和初始化IMapper对象作为这些测试的一部分.
我使用XUnit作为测试框架,使用Ninject来处理依赖注入.
我习惯使用静态AutoMapper方法,并转而使用IMapper接口,这是我的一个存储库构造函数中的参数.
我有一个继承NinjectModule基类的DependencyRegistrar类.
我的加载方法如下:
public override void Load()
{
var automapperConfig = new MapperConfiguration(cfg => { cfg.AddProfile<AutoMapperProfile>(); });
automapperConfig.AssertConfigurationIsValid();
var mapper = automapperConfig.CreateMapper();
Bind<IMapper>().ToConstant(mapper).InSingletonScope();
Bind<IUserManager>().To<UserManager>().InTransientScope();
Bind<IUserRepository>().To<UserRepository>().InTransientScope();
}
Run Code Online (Sandbox Code Playgroud)
该模块由API项目中的NinjectWebCommon类加载,但显然在集成测试期间不会加载.
ConfigurationSettingsEntity configurationSettings = new ConfigurationSettingsEntity(ConfigurationManager.AppSettings);
var modules = new INinjectModule[] { new DependencyResolution.DependencyRegistrar(configurationSettings) };
var kernel = new StandardKernel(modules);
Run Code Online (Sandbox Code Playgroud)
所以,我的问题是,加载真正的映射器实现的最佳方法是什么,以便在构建集成测试时我可以将该映射器传递到我的存储库的构造函数中?
UserRepository tester = new UserRepository(mapper);
Run Code Online (Sandbox Code Playgroud) ninject ×10
c# ×7
.net ×2
asp.net ×2
asp.net-mvc ×1
automapper ×1
com-interop ×1
decorator ×1
factory ×1
integration ×1
mocking ×1
nodatime ×1
vb6 ×1
xunit ×1