C# Ninject:在绑定时定义命名约束
目前,我正在重构一个旧项目,并试图用Ninject实现依赖注入 我遇到了一个或多或少简单的问题。我找到了一个有效的解决方案,但我不确定这是否是解决这个问题的最佳方法 我试图尽可能准确地解释情况: 我有一个接口C# Ninject:在绑定时定义命名约束,c#,dependency-injection,ninject,C#,Dependency Injection,Ninject,目前,我正在重构一个旧项目,并试图用Ninject实现依赖注入 我遇到了一个或多或少简单的问题。我找到了一个有效的解决方案,但我不确定这是否是解决这个问题的最佳方法 我试图尽可能准确地解释情况: 我有一个接口ITool: public interface ITool { string Caption { get; set; } string Name { get; } IAction[] Actions { get; } } 还有一个抽象类AbstractTool(
ITool
:
public interface ITool
{
string Caption { get; set; }
string Name { get; }
IAction[] Actions { get; }
}
还有一个抽象类AbstractTool
(具体内容与问题无关)
此外,我还有派生类GenericTool
:
public class GenericTool : AbstractTool
{
private readonly string furtherInformation;
public override string FurtherInformation
{
get { return furtherInformation; }
}
public GenericTool (string furtherInformation, string caption, string name, Action[] actions)
: base(caption, name, actions)
{
this.furtherInformation= furtherInformation;
}
}
在某一点上,这个GenericTool
被使用并实例化了几次,如下所示:
new OtherObject(
{
new List<GenericTool>
{
new GenericTool("info1","caption1","name1", new IActions[]
{ new Action1(), new Action2()}),
new GenericTool("info2","caption2","name2", new IActions[]
{ new Action3(), new Action4()}),
...
}
}...
操作的绑定:
Bind<IAction>.To<Action1>().Named("SpecialTool1Action");
Bind<IAction>.To<Action2>().Named("SpecialTool1Action");
Bind<IAction>.To<Action3>().Named("SpecialTool2Action");
Bind<IAction>.To<Action4>().Named("SpecialTool2Action");
函数GetLateNamedConstructorArgument
:
private IAction[] GetLateNamedConstructorArgument(IContext context)
{
IEnumerable<IAction> actions= context.Kernel.
GetAll<IAction>("SpecialTool1Action");
return actions.ToArray();
}
private IAction[]GetLateNamedConstructorArgument(IContext上下文)
{
IEnumerable actions=context.Kernel。
GetAll(“特殊工具1行动”);
返回操作。ToArray();
}
对于上一个解决方案,我在没有创建几十个类的情况下得到了相同的结果
但是有没有更好的办法来解决这个问题呢?我可以用其他方式声明所需绑定的名称吗?可能还有其他的工作吗
编辑
我想象这样的情况:
Bind<ITool>().To<GenericTool>()
...
.WithConstructorArgument("actions", [Named("SpecialTool1Action")]);
Bind().To())
...
.带有构造函数参数(“操作”,命名为(“SpecialTool1操作”));
Ninject使用
SpecialTool1Action
名称注入所有操作 沿着这条路线走下去的问题是,正如在的文档中所提到的,这通常是错误的
这里更好的方法是使用模式
抽象工厂模式提供了一种封装一组
具有共同主题但未指定主题的单个工厂
具体课程
基本上,您不是让DI容器在代码中传播以满足复杂的需求,而是请求工厂并使用它们创建所需的实例
Ninject提供了几种实现方法,例如
在Ninject v3中,您可以使用扩展。这个文档链接有一大堆示例代码。以下是说明该概念的主要内容:
public class Foo
{
readonly IBarFactory barFactory;
public Foo(IBarFactory barFactory)
{
this.barFactory = barFactory;
}
public void Do()
{
var bar = this.barFactory.CreateBar();
...
}
}
public interface IBarFactory
{
Bar CreateBar();
}
根据您的回答,我可以创建一个
IGenericToolFactory
或IActionFactory
。如果我在OtherObject
中使用IGenericToolFactory
,我需要声明我要使用的工具的具体信息(在OtherObject
中)。但这不符合我的要求,因为OtherObject
也用于GenericTool
的不同实例。(我可以有多个OtherObject
的实例以及其他具有其他操作的GenericTools)。此外,我无法在不修改它的情况下替换OtherObject
中的工具。然而,如果我要为此使用AbstractFactory
,我仍然不知道如何将正确的工具与正确的操作连接起来。
private IAction[] GetLateNamedConstructorArgument(IContext context)
{
IEnumerable<IAction> actions= context.Kernel.
GetAll<IAction>("SpecialTool1Action");
return actions.ToArray();
}
Bind<ITool>().To<GenericTool>()
...
.WithConstructorArgument("actions", [Named("SpecialTool1Action")]);
public class Foo
{
readonly IBarFactory barFactory;
public Foo(IBarFactory barFactory)
{
this.barFactory = barFactory;
}
public void Do()
{
var bar = this.barFactory.CreateBar();
...
}
}
public interface IBarFactory
{
Bar CreateBar();
}