查看以下代码,在哪里处理具有接口的单个绑定和命名绑定的情况,按照此处的建议使用抽象工厂
Parameterized Factories Using Ninject
这里的挑战是,我需要引入IEnumerable<T> bankingOperationList
而不是T bankingOperationList
,因为对于命名绑定,它总是使用抽象工厂注入Func<string,T> bankingOperationFunc
,但如果我不这样做使用上面提到的IEnumerable<T>
会导致异常,由于这个甚至是非命名的单一绑定,我需要使用类似的东西:
bankingOperationList.FirstOrDefault().Withdraw()
,即使我知道只有一个依赖。
另一个挑战是,对于某些命名绑定,在少数情况下它有30-40个绑定,当我可以将T bankingOperationList
默认为null时,这将被不必要地填充,因为它不是必需的。如果问题需要进一步澄清,请告诉我。下面的工作控制台项目。
public interface IBankingOperation
{
void Withdraw();
}
public class BankingOperationOne : IBankingOperation
{
public BankingOperationOne()
{
Console.WriteLine("Testing Constructor :: One :: Empty");
}
public void Withdraw()
{
Console.WriteLine("Money Withdrawl Operation One");
}
}
public class BankingOperationTwo : IBankingOperation
{
public BankingOperationTwo()
{
Console.WriteLine("Testing Constructor :: Two :: Empty");
}
public void Withdraw()
{
Console.WriteLine("Money Withdrawl Operation Two");
}
}
// Ninject Bindings
public class Bindings : NinjectModule
{
public override void Load()
{
Bind<IBankingOperation>().To<BankingOperationOne>()
.Named("A");
Bind<IBankingOperation>().To<BankingOperationTwo>()
.Named("B");
Bind<Func<string,IBankingOperation>>().ToMethod(ctx => name => ctx.Kernel.Get<IBankingOperation>(name));
}
}
public class BankTran<T> where T : IBankingOperation
{
private IEnumerable<T> bankingOperationList = null;
private Func<string,T> bankingOperationFunc;
public BankTran(IEnumerable<T> boList = null,
Func<string,T> boFunc = null)
{
bankingOperationList = boList;
bankingOperationFunc = boFunc;
}
public void DoOperation(string identifier = null)
{
if(bankingOperationFunc != null)
bankingOperationFunc(identifier).Withdraw();
else
bankingOperationList.FirstOrDefault().Withdraw();
Console.WriteLine("Transaction Successful ");
}
}
class Program
{
static void Main(string[] args)
{
var kernel = new StandardKernel();
kernel.Load(Assembly.GetExecutingAssembly()); // Load from Bindings (derived from NinjectModule)
var transaction = kernel.Get<BankTran<IBankingOperation>>();
transaction.DoOperation("A");
}
}
编辑1,根据jbl的响应
public interface IBankingOperation<T>
{
void Withdraw();
}
public class BankingOperationOne : IBankingOperation<TestOne>
{
public BankingOperationOne()
{
Console.WriteLine("Testing Constructor :: One :: Empty");
}
public void Withdraw()
{
Console.WriteLine("Money Withdrawl Operation One");
}
}
public class BankingOperationTwo : IBankingOperation<TestTwo>
{
public BankingOperationTwo()
{
Console.WriteLine("Testing Constructor :: Two :: Empty");
}
public void Withdraw()
{
Console.WriteLine("Money Withdrawl Operation Two");
}
}
public class TestOne { }
public class TestTwo { }
// Ninject Bindings
public class Bindings : NinjectModule
{
public override void Load()
{
Bind<IBankingOperation<TestOne>>().To<BankingOperationOne>().Named("A");
Bind<IBankingOperation<TestOne>>().To<BankingOperationOne>().Named("B");
Bind<IBankingOperation<TestOne>>().To<BankingOperationOne>().WhenInjectedInto(typeof(BankTran<TestOne>));
Bind<Func<string, IBankingOperation<TestOne>>>().ToMethod(ctx => name => ctx.Kernel.Get<IBankingOperation<TestOne>>(name));
Bind<IBankingOperation<TestTwo>>().To<BankingOperationTwo>();
}
}
public class BankTran<T> where T : class
{
private IBankingOperation<T> bankingOperation;
private Func<string, IBankingOperation<T>> bankingOperationFunc;
public BankTran(IBankingOperation<T> bo = null,
Func<string, IBankingOperation<T>> boFunc = null)
{
bankingOperation = bo;
bankingOperationFunc = boFunc;
}
public void DoOperation(string identifier = null)
{
if (bankingOperationFunc != null && identifier != null)
bankingOperationFunc(identifier).Withdraw();
else if (bankingOperation != null)
bankingOperation.Withdraw();
Console.WriteLine("Transaction Successful ");
}
}
class Program
{
static void Main(string[] args)
{
var kernel = new StandardKernel(new NinjectSettings { AllowNullInjection = true});
kernel.Load(Assembly.GetExecutingAssembly()); // Load from Bindings (derived from NinjectModule)
var transaction = kernel.Get<BankTran<TestOne>>("A"); // Not Working
// var transaction = kernel.Get<BankTran<TestOne>>(); // Working
transaction.DoOperation();
}
}
答案 0 :(得分:1)
假设BankingOperationOne
是您的默认行为,
在Load方法中添加以下行应该允许在BankTran构造函数中用IEnumerable<T>
替换T
:
Bind<IBankingOperation>().To<BankingOperationOne>().WhenInjectedInto(typeof(BankTran<>));
另一种解决方案是仅为默认行为定义命名绑定
Bind<IBankingOperation>().To<BankingOperationOne>().Named("__DefaultBehaviour");
然后
public void DoOperation(string identifier = "__DefaultBehaviour")
{
if (bankingOperationFunc != null)
bankingOperationFunc(identifier).Withdraw();
Console.WriteLine("Transaction Successful ");
}
修改:
您应该使用Ninject.Extenstions.Factory nuget包。 使用此包,以下代码似乎满足您的要求。
public interface IBankingOperation<T>
{
void Withdraw();
}
public interface IBankingOperationFactory<T>
{
IBankingOperation<T> GetBankingOperation(string name);
}
public class BankingOperationOne : IBankingOperation<TestOne>
{
public BankingOperationOne()
{
Console.WriteLine("Testing Constructor :: One :: Empty");
}
public void Withdraw()
{
Console.WriteLine("Money Withdrawl Operation One");
}
}
public class BankingOperationTwo : IBankingOperation<TestTwo>
{
public BankingOperationTwo()
{
Console.WriteLine("Testing Constructor :: Two :: Empty");
}
public void Withdraw()
{
Console.WriteLine("Money Withdrawl Operation Two");
}
}
public class TestOne { }
public class TestTwo { }
// Ninject Bindings
public class Bindings : NinjectModule
{
public override void Load()
{
Bind<IBankingOperation<TestOne>>().To<BankingOperationOne>().Named("A");
Bind<IBankingOperation<TestOne>>().To<BankingOperationOne>().Named("B");
Bind<IBankingOperation<TestOne>>().To<BankingOperationOne>().WhenInjectedInto(typeof(BankTran<TestOne>));
Bind<IBankingOperationFactory<IBankingOperation<TestOne>>>().ToFactory();
Bind<IBankingOperation<TestTwo>>().To<BankingOperationTwo>();
}
}
public class BankTran<T> where T : class
{
private IBankingOperation<T> bankingOperation;
private IBankingOperationFactory<T> _bankingOperationFactory;
public BankTran(IBankingOperation<T> bo = null,
IBankingOperationFactory<T> bankingOperationFactory = null)
{
bankingOperation = bo;
_bankingOperationFactory = bankingOperationFactory;
}
public void DoOperation(string identifier = null)
{
if (_bankingOperationFactory != null && identifier != null)
_bankingOperationFactory.GetBankingOperation(identifier).Withdraw();
else if (bankingOperation != null)
bankingOperation.Withdraw();
Console.WriteLine("Transaction Successful ");
}
}
class Program
{
static void Main(string[] args)
{
var kernel = new StandardKernel(new NinjectSettings { AllowNullInjection = true });
kernel.Load(Assembly.GetExecutingAssembly()); // Load from Bindings (derived from NinjectModule)
var transaction = kernel.Get<BankTran<TestOne>>();
transaction.DoOperation();
transaction.DoOperation("A");
transaction.DoOperation("B");
}
}