我有一个WPF视图\视图模型绑定模式,我想通过名称解析Ninject的依赖关系,而不是类型或类型+名称.我想用Ninject命名我的视图模型,然后通过这个名称引用视图中的视图模型进行视图注入(通过Caliburn.Micro).
我意识到在实践中可以使用相同的名称注册多个类型,但我想要一个约定类型模式,并且我愿意接受这种情况.我只需要解决"对象"以使WPF绑定工作.
例如,我有什么方法可以:
我通过Ninject(2.2.1.4)Extensions.Logging.Log4net(2.2.0.4)使用Log4Net(1.2.10)时遇到问题,通过NuGet安装.
当我直接访问Log4Net时:
var logger = log4net.LogManager.GetLogger("Log4NetLoggerTest");
logger.Debug("foo { bar");
Run Code Online (Sandbox Code Playgroud)
结果是:
2011-08-29 10:02:02,071 [9] DEBUG Log4NetLoggerTest foo { bar
Run Code Online (Sandbox Code Playgroud)
但是,当通过Ninject访问记录器时:
using (IKernel kernel = new StandardKernel())
{
var ninjectLogger = kernel.Get<NinjectLoggerTest>();
ninjectLogger.Log.Debug("foo { bar");
}
Run Code Online (Sandbox Code Playgroud)
NinjectLoggerTest就是这样的:
using Ninject.Extensions.Logging;
namespace TestApp
{
public class NinjectLoggerTest
{
public NinjectLoggerTest(ILogger log)
{
Log = log;
}
public ILogger Log;
}
}
Run Code Online (Sandbox Code Playgroud)
出乎意料的是,结果是:
2011-08-29 10:29:27,114 [10] DEBUG TestApp.NinjectLoggerTest <log4net.Error>Exception during StringFormat: Input string was not in a correct format. <format>foo { bar</format><args>{}</args></log4net.Error>
Run Code Online (Sandbox Code Playgroud)
更糟糕的是,当使用ILogger的Trace方法时,mscorlib.dll中存在类型'System.FormatException'的第一次机会异常
难道我做错了什么?我该如何解决这个问题?
TIA
我最初使用了一些自定义代码来处理Web API中的依赖项解析,它运行正常.我遇到的问题是我想将过滤器绑定到我的控制器范围,就像使用MVC一样.例如,Kernel.BindFilter.新的Ninject.We.WebApi包具有我想要的绑定扩展名,但是一旦我将它添加到我的项目中,我就会收到以下错误.我没有更改任何代码,只是引用DLL.
使用从IFilterProvider到DefaultFilterProvider的绑定激活IFilterProvider时出错在两个服务的构造函数之间检测到循环依赖.
激活路径:3)将依赖项IFilterProvider注入到DefaultFilterProviders类型的构造函数的参数defaultFilterProviders中2)将依赖项DefaultFilterProviders注入参数filterProviders类型为DefaultFilterProvider的构造函数1)请求IFilterProvider
建议:1)确保您未在任何服务实现上声明IFilterProvider的依赖项.2)考虑将服务组合成一个服务以消除周期.3)使用属性注入而不是构造函数注入,如果需要在注入属性值后运行初始化逻辑,则实现IInitializable.
at Ninject.Activation.Context.Resolve()at Ninject.KernelBase.<> c__DisplayClass15.b__f(IBinding binding)at System.Linq.Enumerable.WhereSelectListIterator
2.MoveNext() at System.Linq.Enumerable.<CastIterator>d__b11.MoveNext()at System.Linq.Enumerable.d__142.MoveNext() at System.Collections.Generic.List1..ctor(在System.Linq.Enumerable.d__14 1的System.Web.Http.Controllers.HttpActionDescriptor.b__0(IFilterProvider fp)的Ninject.Web.WebApi.Filter.DefaultFilterProvider.GetFilters(HttpConfiguration配置,HttpActionDescriptor actionDescriptor)中有IEnumerable 1源码. ctor(在System.Linq.Buffer 1源上的IEnumerable 1.d__0.MoveNext())在System.Linq.Enumerable.d__a0 1..ctor(System.Collections.Generic.List 1集合中的IEnumerable 1.MoveNext()) at System.Linq.Enumerable.ToList [TSource](IEnumerable 1.CreateValue()---从抛出异常的先前位置开始的堆栈跟踪结束---在System.Lazy的System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()处`1.get_Value()在System.Web.Http.Controllers.HttpActionDescriptor.GetFilterPipeline() 在System.Web.Http.Controller System.Web.Http上System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsyncCore(HttpRequestMessage请求,CancellationToken cancellationToken)的System.Web.Http.ApiController.ExecuteAsync(HttpControllerContext controllerContext,CancellationToken cancellationToken)中的s.HttpActionDescriptor.GetFilterGrouping(). Dispatcher.HttpControllerDispatcher.d__0.MoveNext()1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable2.MoveNext() at System.Linq.Buffer1 source) at System.Linq.OrderedEnumerable1..ctor(IEnumerable1.MoveNext() at System.Web.Http.Controllers.HttpActionDescriptor.<RemoveDuplicates>d__3.MoveNext() at System.Linq.Buffer1 source) at System.Linq.Enumerable.<ReverseIterator>d__a01..ctor(IEnumerable1 source) at System.Web.Http.Controllers.HttpActionDescriptor.InitializeFilterPipeline() at System.Lazy
我开始使用Ninject,在这个相对较小的项目上,我遇到了一个问题:我有这个课程
class SomeService : ISomeService
Run Code Online (Sandbox Code Playgroud)
这取决于
class BizLogicModule : IBizLogicModule
Run Code Online (Sandbox Code Playgroud)
而这又取决于
class DataRepository : IDataRepository
Run Code Online (Sandbox Code Playgroud)
在DataRepository有一个构造函数,看起来像:
DataRepository(BizEntityModel context)
Run Code Online (Sandbox Code Playgroud)
现在,我需要能够使用BizEntityModel跨多个实例的单个IDataRepository实例.
我还需要创造IDataRepository一个人的生活IBizLogicModule.我IBizLogicModule不知道Ninject,我想保持这种方式.
所以我的问题是:如何使用Ninject内核连接所有这些,同时:
不必在层周围传递内核实例.
保持代码可读性接近于之前的Ninject(我只是使用工厂方法进行新操作).
到目前为止我接线的简单部分是:
Bind<SomeService>().To<ISomeService>();
Bind<BizLogicModule>().To<IBizLogicModule>();
Bind<DataRepository>().To<IDataRepository>();
Bind<BizEntityModel>().To<BizEntityModel>(); //ToSelf()
// .WithConstructorArgument(context => Kernel.Get<BizEntityModel>)
Run Code Online (Sandbox Code Playgroud)
非常感谢您的指导
编辑:谢谢你的回答!
这里有一些请求的数据:
BizEntityModel在Ninject注册(代码更新).
如果我正确理解:我可以创建的实例IDataRepository中IBizLogicModule使用了"工厂方法".但这让我失望:
1)我需要传递一个BizEntityModel工厂方法,有时候是新的,有时是现有的实例.使用工厂方法,每次都会重新创建一个.
2)这SomeService是另一个程序集中的问题,只有它有一个引用Ninject.dll?
所以我只是试图测试我的模块,通常我会用给定的模块创建一个内核然后尝试获取一个实例,但是这个场景涉及一些模块,如果我能检查某些模块有更好的话会更好访问某些绑定(即实现和接口)
有没有办法检查给定类型的绑定是否可用而没有创建类的实例(即所以我不必确保那些依赖项存在)?
所以我花了一些时间与ASP.NET MVC 2(目前坚持使用Visual Studio 2008),现在已经开始使用Ninject 2.2及其MVC集成.我从以下位置下载了Ninject 2.2和Ninject.Web.Mvc:
https://github.com/downloads/ninject/ninject/Ninject-2.2.0.0-release-net-3.5.zip
https://github.com/downloads/ninject/ninject.web.mvc/Ninject.Web.Mvc2 -2.2.0.0-release-net-3.5.zip
并在我的MVC 2项目中引用它们.我的Global.asax.cs文件看起来像这样(几乎是Ninject.Web.Mvc自述文件所说的):
using System;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Ninject.Web.Mvc;
using Ninject;
namespace Mvc2 {
public class MvcApplication : NinjectHttpApplication {
public static void RegisterRoutes(RouteCollection routes) {
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
}
protected override void OnApplicationStarted() {
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
}
protected override IKernel CreateKernel() { …Run Code Online (Sandbox Code Playgroud) 所以,假设我有一个界面IThingFactory:
public interface IThingFactory
{
Thing GetThing(int thingId);
}
Run Code Online (Sandbox Code Playgroud)
现在,假设我有一个Thing从数据库中检索s 的具体实现.现在,我们还说我有一个具体的实现,它包装了一个现有的,IThingFactory并且Thing在命中包装之前检查是否存在于内存缓存中IThingFactory.就像是:
public class CachedThingFactory : IThingFactory
{
private IThingFactory _wrapped;
private Dictionary<int, Thing> _cachedThings;
public CachedThingFactory(IThingFactory wrapped)
{
this._wrapped = wrapped;
_cachedThings = new Dictionary<int,Thing>();
}
public Thing GetThing(int thingId)
{
Thing x;
if(_cachedThings.TryGetValue(thingId, out x))
return x;
x = _wrapped.GetThing(thingId);
_cachedThings[thingId] = x;
return x;
}
}
Run Code Online (Sandbox Code Playgroud)
如何使用依赖注入来处理这样的场景,例如Ninject,以便我可以配置DI容器,以便我可以注入或删除像这样的缓存代理,或者说,执行日志记录的东西,或(在这里插入)?
我有一个工厂,如下所示:
public IFoo GetFoo(IFile file)
{
return _kernel.Get<IFoo>(new ConstructorArgument("file", file));
}
Run Code Online (Sandbox Code Playgroud)
它工作正常,直到我使用 Moq 来模拟IFoo. 在模拟中没有名为 file 的构造函数参数,我得到一个 Ninject.ActivationException。
我应该如何解决这个问题?
使用 Ninject Factory 扩展,您可以自动生成工厂,并让工厂将参数传递给类的构造函数。以下测试通过:
public interface IBar
{
int Foo { get; }
}
public class Bar : IBar
{
int _foo;
public Bar(int foo) { _foo = foo; }
public int Foo { get { return _foo; } }
}
public interface IBarFactory
{
IBar CreateTest(int foo);
}
[Test]
public void ExecuteTest()
{
var kernel = new StandardKernel();
kernel.Bind<IBar>().To<Bar>();
kernel.Bind<IBarFactory>().ToFactory();
var factory = kernel.Get<IBarFactory>();
var actual = factory.CreateTest(42);
Assert.That(actual, Is.InstanceOf<Bar>());
}
Run Code Online (Sandbox Code Playgroud)
但是,在我的特定问题中,我希望它将工厂参数传递给我正在构建的类的依赖项,而不是类本身,如下所示:
public interface IBarContainer
{
IBar Bar { …Run Code Online (Sandbox Code Playgroud) 我有一个非常简单的Ninject绑定:
Bind<ISessionFactory>().ToMethod(x =>
{
return Fluently.Configure()
.Database(SQLiteConfiguration.Standard
.UsingFile(CreateOrGetDataFile("somefile.db")).AdoNetBatchSize(128))
.Mappings(
m => m.FluentMappings.AddFromAssembly(Assembly.Load("Sauron.Core"))
.Conventions.Add(PrimaryKey.Name.Is(p => "Id"), ForeignKey.EndsWith("Id")))
.BuildSessionFactory();
}).InSingletonScope();
Run Code Online (Sandbox Code Playgroud)
我需要的是用参数替换"somefile.db".类似的东西
kernel.Get<ISessionFactory>("somefile.db");
Run Code Online (Sandbox Code Playgroud)
我如何实现这一目标?
ninject-2 ×10
ninject ×8
c# ×6
.net ×2
asp.net-mvc ×1
c#-4.0 ×1
log4net ×1
moq ×1
ninject.web ×1