使用ninject将依赖项注入Model类或非控制器类

时间:2012-11-03 19:42:49

标签: asp.net-mvc-3 entity-framework ninject repository-pattern

我在mvc 3(steven sanderson Scaffolder)的存储库模式中使用Ninject 3。
并且在ninject中我有“NinjectWebCommon”类,它在“RegisterServices”方法中解决了依赖关系,我想我已经准备好了。

  private static void RegisterServices(IKernel kernel)
  {
     kernel.Bind<ICityRepository>().To<CityRepository>();
     kernel.Bind<IVillageRepository >().To<VillageRepository>();
  }

我使用构造函数注入在控制器中使用我的存储库,一切都很好。

public class CityController : Controller
{
   private readonly ICityRepository cityRepository;

   // If you are using Dependency Injection, you can delete the following constructor
   //public CityController() : this(new CityRepository())
   //{
   //}

   public CityController(ICityRepository cityRepository)
   {
      this.cityRepository = cityRepository;
   }

  // .........
}

但是当我使用属性注入或字段注入在其他类(如模型(实体)类)中使用此存储库时,依赖项未解析,并且在我的属性或字段上获得空引用异常。

[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; }
}

我不知道为什么会这样。那么问题是什么?如何在非控制器类中使用存储库? 提前致谢。

1 个答案:

答案 0 :(得分:3)

你的问题是,你期待着魔力。您为存储库注入了一个实现,然后您希望该存储库创建的数据对象注入创建存储库的引用。

首先,这不起作用。存储库的实现将在您的实体上调用new()(或Activator.CreateInstance),而不是从Ninject Kernel或Factory请求实例。你可以重写存储库(如果你在那里使用EF会变得更棘手......)但是它可能不值得麻烦。

最重要的是,你根本不应该那样做。 Entities shouldn't depend on repositories,甚至不是他们的接口。

编辑:现在我明白为什么你要在你的模型中看到一个回购。我推荐的是静态工厂。

public class Factories
{
public static readonly Instance = new Factories();
[Inject]
public Func<IVillageRepository> VillageRepo  {get; set;}
}

然后从您的Ninject初始化代码(绑定IVillageRepository)中调用Kernel.Inject(Factories.Instance);。然后将您的可验证实现修改为Factories.Instance.VillageRepo().Find(...);