3

mvc 3(steven sanderson Scaffolder)のリポジトリパターンでNinject3を使用しています。
ninjectには、「RegisterServices」メソッドで依存関係を解決したクラス「NinjectWebCommon」があり、準備ができていると思います。

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

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

しかし、プロパティインジェクションやフィールドインジェクションを使用するModel(Entity)クラスなどの他のクラスでこのリポジトリを使用すると、依存関係が解決されず、プロパティまたはフィールドでnull参照例外が発生します。

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

なぜこれが起こっているのか分かりません。では、問題は何ですか?コントローラー以外のクラスでリポジトリを使用するにはどうすればよいですか?
前もって感謝します。

4

1 に答える 1

3

あなたの問題は、あなたが魔法を期待しているということです。リポジトリの実装を注入すると、そのリポジトリによって作成されたデータオブジェクトに、作成中のリポジトリの参照が注入されることが期待されます。

まず第一に、それはそのようには機能しません。リポジトリの実装は、Ninjectカーネルまたはファクトリからのインスタンスを要求するのではなく、エンティティでnew()(またはActivator.CreateInstance)を呼び出します。リポジトリを書き直すこともできますが(そこでEFを使用している場合は、より複雑になります...)、おそらく面倒な価値はありません。

それに加えて、それはまったく必要ないはずです。エンティティはリポジトリに依存するべきではありません。インターフェースさえも依存しないでください。

編集:モデルにリポジトリを表示する理由がわかりました。私がお勧めするのは、おそらく静的ファクトリです。

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

次にKernel.Inject(Factories.Instance);、Ninject初期化コード(IVillageRepositoryをバインドする場所)から呼び出します。次に、検証可能な実装を次のように変更しますFactories.Instance.VillageRepo().Find(...);

于 2012-11-05T15:41:49.687 に答える