Asp.net mvc 3 使用ninject向模型类或非控制器类注入依赖关系
我在mvc 3的存储库模式中使用Ninject 3(steven sanderson Scaffolder)。Asp.net mvc 3 使用ninject向模型类或非控制器类注入依赖关系,asp.net-mvc-3,entity-framework,ninject,repository-pattern,Asp.net Mvc 3,Entity Framework,Ninject,Repository Pattern,我在mvc 3的存储库模式中使用Ninject 3(steven sanderson Scaffolder)。 在ninject中,我有一个类“NinjectWebCommon”,在“RegisterServices”方法中,我解决了依赖关系,我想我已经准备好了 private static void RegisterServices(IKernel kernel) { kernel.Bind<ICityRepository>().To<CityReposit
在ninject中,我有一个类“NinjectWebCommon”,在“RegisterServices”方法中,我解决了依赖关系,我想我已经准备好了
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ICityRepository>().To<CityRepository>();
kernel.Bind<IVillageRepository >().To<VillageRepository>();
}
但是,当我在其他类(如使用属性注入或字段注入的模型(实体)类)中使用此存储库时,依赖关系没有得到解决,并且我的属性或字段出现空引用异常
[MetadataType(typeof(CityMetadata))]
public partial class City : IValidatableObject
{
[Inject]
public IVillageRepository VillageRepo { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
var village = VillageRepo.Find(5); // will throw null reference exception on "VillageRepo"
}
}
public partial class CityMetadata
{
[ScaffoldColumn(false)]
public int ID { get; set; }
[Required(ErrorMessage = MetadataErrorMessages.Required)]
[StringLength(50, ErrorMessage = MetadataErrorMessages.ExceedMaxLength)]
public string Name { get; set; }
}
[元数据类型(typeof(CityMetadata))]
公共部分类城市:IValidatableObject
{
[注入]
公共IVillageRepository VillageRepo{get;set;}
公共IEnumerable验证(ValidationContext ValidationContext)
{
var village=VillageRepo.Find(5);//将在“VillageRepo”上引发null引用异常
}
}
公共部分类城市元数据
{
[脚手架立柱(假)]
公共int ID{get;set;}
[必需(ErrorMessage=MetadataErrorMessages.Required)]
[StringLength(50,ErrorMessage=MetadataErrorMessages.ExceedMaxLength)]
公共字符串名称{get;set;}
}
我不知道为什么会这样。那么问题是什么?我如何在非控制器类中使用存储库?提前谢谢 你的问题是,你在期待魔法。为存储库注入一个实现,然后期望该存储库创建的数据对象被注入创建存储库的引用 首先,那不是那样的。存储库的实现将在实体上调用new()(或Activator.CreateInstance),而不是从Ninject内核或工厂请求实例。您可以重写存储库(如果您在那里使用EF,它会变得更复杂…),但这可能不值得这么麻烦 最重要的是,你根本不需要这些,我甚至不知道他们的接口 编辑:现在我明白了为什么您希望在模型中看到回购。我推荐的是一个静态工厂
public class Factories
{
public static readonly Instance = new Factories();
[Inject]
public Func<IVillageRepository> VillageRepo {get; set;}
}
公共类工厂
{
公共静态只读实例=新工厂();
[注入]
public Func VillageRepo{get;set;}
}
然后调用
Kernel.Inject(Factories.Instance)代码>来自Ninject初始化代码(绑定IVillageRepository的地方)。然后将可验证实现修改为Factories.Instance.VillageRepo().Find(…)代码>您不应该在实体上使用注入(查看Ninject标签或一般文章,您很快就会被说服)。你并没有真正说出你正在做什么,你期望发生什么,但事实并非如此。我猜你并不是在向Ninject询问你的实体/使用内核。注入-记住DI容器不会用magic interception替换IL中的new
s(你可能知道,但请编辑问题以澄清这一点),如果是有线的,请道歉。但是我没有在实体中使用注入。因此,如果我不能使用注入,我该如何解决依赖关系?我的意思是,当我使用接口类时,它必须知道是哪个类实现了它。如果我这样实例化:IVillageRepository villageRepo=new VillageRepository()代码>我将打破整个模式,对吗?我只想通过构造函数注入在控制器类中使用存储库类,而不仅仅是在控制器类中,因为很明显,我不需要在控制器中使用数据库。那怎么办?对不起,英语不好。你也不应该那样做。如果需要传递一种生成注入实例的方法,可以使用它来生成Func
方法。我还建议,这是一项极好的投资,有助于了解自上而下的最佳方法。在这本书出版的过程中,你的下一步是阅读马克·希曼的最重要的答案,然后其他人重新注入实体。你的问题最终应该得到+1。你真的不同意答案也是这样吗?@RubenBartelink:事实上,我想测试答案,然后接受并加上一个。但是他妈的:)接受和+1。谢谢。但我认为这是一种蔑视。我的问题不是期待魔法,我的问题是缺乏知识。我这样写问题是为了让我的问题变得更明显,所以它显然是不可能的,你这么快就得到了答案。我来看看。@JalaliShakib:我不是说你故意想要魔法:)这就是为什么我突出显示了新的vs内核。在这里获取问题。您的代码(以及一些工厂代码)可以从Ninject获得。EF永远不会这样做。顺便说一句,你可以纠正Factories.Instance.VillageRepo().Find(…)代码>因为VillageRepo是一个属性而不是一个方法。谢谢。VillageRepo
是一个属性,它返回一个Func
。()
用于执行Func
以获取ivillagepositional
的实例。在您询问之前,存储存储库的单个实例是非常不明智的,因为它可能导致终生问题。最好将生存期处理留给IoC容器,每次都从工厂请求一个实例(可能是新实例,也可能不是新实例)。您可能需要Ninject.Extensions.factory模块。IIRC为基于Func的工厂带来支持。。。
public class Factories
{
public static readonly Instance = new Factories();
[Inject]
public Func<IVillageRepository> VillageRepo {get; set;}
}