我一直在阅读这两种解决依赖关系的方法,并找到了一些 ninject 实现的示例代码。
对于服务定位器遵循类似
public class NinjectDependencyResolver : NinjectDependencyScope, IDependencyResolver
{
IKernel kernel;
public NinjectDependencyResolver(IKernel kernel)
: base(kernel)
{
this.kernel = kernel;
}
public IDependencyScope BeginScope()
{
return new NinjectDependencyScope(kernel.BeginBlock());
}
}
Run Code Online (Sandbox Code Playgroud)
和
public class NinjectDependencyScope : IDependencyScope
{
IResolutionRoot resolver;
public NinjectDependencyScope(IResolutionRoot resolver)
{
this.resolver = resolver;
}
public object GetService(Type serviceType)
{
if (resolver == null)
throw new ObjectDisposedException("this", "This scope has been disposed");
return resolver.TryGet(serviceType);
}
public System.Collections.Generic.IEnumerable<object> GetServices(Type serviceType)
{
if (resolver == null)
throw new …Run Code Online (Sandbox Code Playgroud) c# dependency-injection ninject inversion-of-control compositionroot
我有一个使用 Xamarin.iOS 开发的 iOS 应用程序,它使用 Ninject 3.3.0 进行 IoC。我能够毫无问题地绑定接口和实现,但是我得到了PlatformNotSupportedException解决这些绑定的IResolutionRoot.Get<T>(). 我正在连接的 Macbook 上启动模拟器。我创建了一个测试(空白)iOS 应用程序来演示该问题。以下是相关行:
[Register("AppDelegate")]
public class AppDelegate : UIApplicationDelegate
{
...
public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
{
...
var kernel = new StandardKernel();
kernel.Bind<IFoo>().To<Foo>();
var test = kernel.Get<IFoo>(); //exception thrown here
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
这是堆栈跟踪的顶部(可以提供更多):
" 在 System.Reflection.Emit.DynamicMethod..ctor (System.String name, System.Type returnType, System...."
根据该站点,内核为其绑定创建了这些 DynamicMethod。既然.Net Standard 2.0支持Ninject ,为什么我会从这么简单的操作中得到这个异常?
大家好,我对 WPF 有一些经验,但我仍处于 MVVM 的开始阶段,现在我想将 DI 与 ninject 一起使用。当我使用表单时,我通常使用 ninject,通过创建一个带有绑定的内核来加载并在构造函数中插入参数,我发现现在这是不可能的,因为我必须使用 DataContext。我在视图模型中有一个带有按钮和构造函数的主窗口,为了使用窗口中的按钮,我需要从构造函数中的绑定传递参数,但如果这样做,我会收到错误,因为 datacontext想要一个无参数构造函数,我相信有一个明显的解决方案,我在 Ninject (站点)上找不到特定的解决方案,并且在线唯一的解决方法使用一些复杂的工厂模式,这似乎有点过头了,有谁知道如何解决这个问题?
主窗口.xaml
<Window x:Class="StretchApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:StretchApp"
xmlns:vm="clr-namespace:StretchApp.ViewModels"
mc:Ignorable="d"
Title="MainWindow" Height="800" Width="800" Background="LightGray"
DataContextChanged="MainWindow_DataContextChanged">
<Window.DataContext>
<vm:MainViewModel/>
</Window.DataContext>
Run Code Online (Sandbox Code Playgroud)
MainWindow.xaml.cs
namespace StretchApp
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window, IHavePassword
{
private IKernel container;
public MainWindow()
{
InitializeComponent();
DataContextChanged += new DependencyPropertyChangedEventHandler(MainWindow_DataContextChanged);
}
void MainWindow_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
var dc = DataContext as IClosableViewModel;
dc.CloseWindowEvent += new …Run Code Online (Sandbox Code Playgroud) Ninject看起来很棒,所以我想在我的项目中使用它.不幸的是,我仍在努力做最琐碎的约束.[Inject]属性编译得很好,但编译器找不到"Bind"命令:
using System;
using Ninject.Core;
using Ninject.Core.Binding;
namespace NinjectTest
{
public interface IFoo
{
void DoSomething();
}
public class Foo : IFoo
{
public void DoSomething()
{
throw new NotImplementedException();
}
}
public class Bar
{
[Inject] private IFoo theFoo;
public Bar()
{
Bind<IFoo>().To<Foo>(); //Compiler Error: "The name 'Bind' does not exist in the current context"
}
}
}
Run Code Online (Sandbox Code Playgroud)
这可能会出错?
我在会话中有一个配置文件对象,其中包含当前登录用户的配置文件信息.我的魔杖能够将它注入我的业务类中,所以我可以在其中进行验证等,而不必在每个方法的参数列表中传递它.
我在我的ninject模块中尝试过类似的东西:
Profile profile = HttpContext.Current.Session["Profile"] as Profile;
Bind<Profile>().ToConstant(profile).InTransientScope();
Run Code Online (Sandbox Code Playgroud)
但是当我在我的aspx中执行Kernel.Get()时,它会以null引用而爆炸.BusinessObject通过构造函数获取配置文件.如果我硬编码配置文件而不是使用HttpContext,那么一切似乎都有效.不确定ToConstant是否可行,我真的在寻找每次创建新BusinessObject时都会得到评估的东西.
UPDATE
似乎要求在页面级对象内联上进行注入对于会话集合来说太早了.如果我移入Kernel.Get调用Page_Load它就可以了.
我有一个看起来像这样的绑定:
kernel.Bind<IRepository<Holiday>>().To<RepositoryBase<Holiday>>();
Run Code Online (Sandbox Code Playgroud)
问题是RepositoryBase采用了一个名为context的UnitOfWork的构造函数参数.这不是,本身就是一个问题.Ninject应该解决它.除了我有两个UnitOfWork实现的事实,两个都使用属性鉴别器绑定.
kernel.Bind<IUnitOfWork>().To<MS_DevEntities>().WhenTargetHas<MsDataAttribute>()
.InRequestScope();
Run Code Online (Sandbox Code Playgroud)
如何指定在创建IRepository时,应该使用MS_DevEntities创建?
当然,我可以这样做:
kernel.Bind<IRepository<Holiday>>().To<RepositoryBase<Holiday>>()
.WithConstructorArgument("context", new MS_DevEntities());
Run Code Online (Sandbox Code Playgroud)
但是,我宁愿让Ninject创建实例,特别是因为我正在使用.InRequestScope()生命周期.
有什么建议?
编辑:
以前,我使用的是如下所示的类:
public class HolidayRepository : RepositoryBase<Holiday>, IHolidayRepository
{
public HolidayRepository([MsData]IUnitOfWork context) : base(context){}
}
Run Code Online (Sandbox Code Playgroud)
但是,我现在发现自己有几十个,但是当我需要创建一个新的存储库时,它们并没有做太多工作,而是增加了额外的工作.我想直接在绑定中映射这些.
EDIT2:
我想我可以做这样的事情,但看起来有点像黑客.有没有更好的办法?
kernel.Bind<MS_DevEntities>().ToSelf().InRequestScope();
kernel.Bind<IRepository<Holiday>>().To<RepositoryBase<Holiday>>()
.WithConstructorArgument("context",
(context) => context.Kernel.Get<MS_DevEntities>());
Run Code Online (Sandbox Code Playgroud) 我的简单例子中有一个小问题.
我有简单的工厂界面:
public interface ICameraFactory
{
ICameraController GetNikonCamera();
ICameraController GetCanonCamera();
}
Run Code Online (Sandbox Code Playgroud)
我将它绑定为工厂:
IKernel kernel = new StandardKernel();
kernel.Bind<ICameraFactory>().ToFactory();
Run Code Online (Sandbox Code Playgroud)
当我尝试转换:
kernel.Bind<ICameraController>().To<NikonCameraController>()
.Named("NikonCamera");
Run Code Online (Sandbox Code Playgroud)
至:
kernel.Bind<ICameraController>().To<NikonCameraController>()
.NamedLikeFactoryMethod<ICameraFactory>(f => f.GetNikonCamera());
Run Code Online (Sandbox Code Playgroud)
它不编译.
例如,这段代码被编译(但很糟糕):
kernel.Bind<ICameraController>()
.ToMethod<ICameraController>(c=>new NikonCameraController())
.NamedLikeFactoryMethod<ICameraController, ICameraFactory>(f => f.GetNikonCamera());
Run Code Online (Sandbox Code Playgroud)
我究竟做错了什么?
Ninject 3.0.1.10
Ninject.Extension.Factory 3.0.1.0
编译错误:https://dl.dropbox.com/u/21806986/Screenshots/shot_19072012_133454.png
我的应用程序中有来自Ninject的IOC.有几个类需要花费大量时间来初始化(从DB或文件中获取一些静态数据缓存).显然,他们需要在处理第一个用户请求之前创建它们.否则会有很高的超时风险.Ninject是否提供了一种方法来告诉内核通过绑定并创建一些?
我只是学习使用Ninject依赖注入,并使用System.IO.Abstractions来抽象文件系统.我试图使用Ninject绑定DirectoryInfoBase到DirectoryInfo如此:
IKernel ninject = new StandardKernel();
ninject.Bind<DirectoryInfoBase>().To<DirectoryInfo>();
Run Code Online (Sandbox Code Playgroud)
但我得到了错误
错误1类型'System.IO.DirectoryInfo'不能用作泛型类型或方法'Ninject.Syntax.IBindingToSyntax.To()'中的类型参数'TImplementation'.没有从'System.IO.DirectoryInfo'到'System.IO.Abstractions.DirectoryInfoBase'的隐式引用转换.C:\ Users\Trevor\Dropbox\Code\PhotoOrganiser\PhotoOrganiser\Program.cs 13 13 PhotoOrganiserApp
我在这里错过了什么?我认为像这样的图书馆的目标是能够执行这些类型的任务吗?
我们正在开发一个Mvc应用程序,我们希望使用nInject来使用依赖注入.目前我们正在维护不同类库"ShopEntities"中的实体,而在我们的mvc应用程序中,我们正在使用这些实体.让我们考虑ShopEntities中的一个类.
namespace ShopEntities
{
public class Customers
{
public int custId {get;set;}
public string custName {get;set;}
public string Address {get;set;}
public string ShippingAddress {get;set;}
}
}
Run Code Online (Sandbox Code Playgroud)
现在,当我们想在我们的mvc应用程序中使用它时,我们创建一个实例并设置如下所示的属性,
public ActionResult Index()
{
ShopEntities.Customers cust = new ShopEntities.Customers();
cust.CustName = "Sam";
cust.IAddress = "xyz";
cust.ShippingAddress = "xyz xyx xyz";
}
Run Code Online (Sandbox Code Playgroud)
如何在这里使用nInject来避免依赖?此外,我们不希望创建接口,因为这在范围上是有限的.提前致谢.
ninject ×10
c# ×8
.net ×2
asp.net ×1
asp.net-mvc ×1
ninject-2 ×1
wpf ×1
xamarin.ios ×1
xaml ×1