Ninject如何避免多个名称绑定
审查下面的代码,在那里照顾的情况下与接口单,并命名为结合数组注射,使用了抽象工厂这里Ninject如何避免多个名称绑定
Parameterized Factories Using Ninject
建议这里面临的挑战是,我需要引入IEnumerable<T> bankingOperationList
而不是T bankingOperationList
,因为对于命名绑定,它将始终使用抽象工厂注入Func<string,T> bankingOperationFunc
,但如果我不使用上面建议的IEnumerable<T>
,则会导致异常,因为这会导致偶数非命名单绑定,我需要使用类似: bankingOperationList.FirstOrDefault().Withdraw()
,即使我知道只会有一个依赖。 另一个挑战是,对于某些命名的绑定,在少数情况下它有30-40个绑定,当我可以将T bankingOperationList
默认为空时,它将被不必要地填充,因为它不是必需的。请让我知道,如果这个问题需要进一步澄清。下方的工作控制台项目。
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();
}
}
假设BankingOperationOne
基于响应是默认的行为, 将在您的Load方法以下行应允许T
更换IEnumerable<T>
你BankTran的构造函数:
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");
}
}
感谢您的详细信息,请检查标记为**编辑1的问题中的编辑,基于jbl的响应**您的代码帮助我运行主要方法中标记的部分没有明确的名称,但它仍然不能帮助运行名称为“A”的版本,这是我的主要挑战 –
@MrinalKamboj不应该他不在你编辑的例子中工作线'var transaction = kernel.Get
这是我标记为非工作的帽子,只是我已将该部分包含在代码中,以便您可以运行并查看错误。没有“A”的其他部分正在工作,正如上面的评论中所建议的那样。 –
注入'Func'是完成工作的一种方法。使用[策略模式](https://stackoverflow.com/a/31971691/)是另一个。这将是清单手头上的“清单”的更清晰的解决方案。也就是说,你不清楚你想要解决什么问题 - 它是从列表中获得“默认”操作吗? – NightOwl888
@ NightOwl888问题是多个相同类型的绑定将由'Func'处理,另一个'IEnumerable '不被使用,它只需要一对一/唯一/未命名的绑定,但仍然需要一个集合,否则对于命名绑定导致异常,它们被不必要地填充。请运行代码并尝试'T bankingOperation'而不是'Banknoperable bankingOperationList'在'BankTran '中,您将会得到我正在谈论的问题 –
@ NightOwl888我回顾了您提供的解决方案,它避免了需要'Func ','ICarFactory []'本身找到了正确的对象,但这样我就能够使当前的解决方案工作得很好,我只是想避免命名绑定需求来填充集合,但Ninject仍然存在线索少在这种情况下,并希望收集填写 –