11

序章:

Ninject Factory Extensionを使用して、単純なオブジェクトファクトリをサービスクラスに注入しています。

これが私のインターフェースとそれを実装する2つのクラスです:

public interface ICar
{
    void Drive();
    void Stop();
}

public class Mercedes : ICar
{
    public void Drive()
    {
      Do mercedes drive stuff...
    }

    public void Stop()
    {
      Do mercedes stop stuff...  
    }

}

public class Ferrari : ICar
{
    public void Drive()
    {
      Do ferrari drive stuff...
    }

    public void Stop()
    {
      Do ferrari stop stuff...  
    }
}

実行時に車を動的に作成するためのオブジェクトファクトリは次のとおりです。

public interface ICarFactory
{
   ICar CreateCar(string carType);
}

public class CarFactory : ICarFactory 
{
   public ICar CreateCar(string carType)
   {
       ICar car;

       switch (type)
       {
           case "mercedes":
                car = new Mercedes();
           break;

           case "ferrari":
               car = new Ferrari();
           break;
       }

       return car;
    }
 }

次に、ninjectファクトリ拡張「ToFactory」メソッドを使用して、自動車ファクトリインターフェイスをバインドします。

public class CarModule : Ninject.Modules.NinjectModule
{
      public override void Load()
      {
           Bind<ICarFactory>().ToFactory();
      }
}

問題:

私のファクトリは期待どおりにサービスクラスに注入され、車のオブジェクトを作成するために使用できますが、ICarを具体的なタイプに適切に解決できないため、ここでninjectが爆発します。MercedesまたはファクトリメソッドFerrariによって返されます。CreateCar()

public CarService(string carType, ICarFactory carFactory)
{
   var car = carFactory.CreateCar(carType);
}

質問:

ここで使用しているファクトリパターンが、ninjectファクトリ拡張の動作と互換性があると仮定すると、実行時に動的に解決されるように、ICar-> Ferrari、ICar->Mercedesなどのバインディングを設定するにはどうすればよいですか。このアプローチ?

ありがとう!

4

1 に答える 1

24

ウィキにカスタムファクトリーの例がありますninject.extension.factory

まず、のカスタム実装を作成して、StandardInstanceProviderデフォルトの工場出荷時の動作をオーバーライドします

public class UseFirstArgumentAsNameInstanceProvider : StandardInstanceProvider
{
    protected override string GetName(System.Reflection.MethodInfo methodInfo, object[] arguments)
    {
        return (string)arguments[0];
    }

    protected override ConstructorArgument[] GetConstructorArguments(MethodInfo methodInfo, object[] arguments)
    {
        return base.GetConstructorArguments(methodInfo, arguments).Skip(1).ToArray();
    }
}

ファクトリのCarModule指定UseFirstArgumentAsNameInstanceProvider(カスタムインスタンスプロバイダー)ICarFactoryと依存関係の名前

public class CarModule : NinjectModule
{
    public override void Load()
    {
        Bind<ICarFactory>()
            .ToFactory(() => new UseFirstArgumentAsNameInstanceProvider());

        Bind<ICar>()
            .To<Mercedes>()
            .Named("Mercedes");

        Bind<ICar>()
            .To<Ferrari>()
            .Named("Ferrari");
    }
}

工場と依存関係を解決する

var factory = kernel.Get<ICarFactory>();

var mercedes = factory.CreateCar("Mercedes");
var ferrari = factory.CreateCar("Ferrari");

ps:ここに完全な例があります

于 2013-01-22T10:22:08.543 に答える