问题描述
也就是说,在C#中,界面中不能有静态方法,而Ninject是基于使用接口?
我的用例是一个类,我希望它有一个静态方法来创建一个
未填充的自身实例。
编辑1
只需在TopologyImp类中添加一个示例, GetRootNodes()方法,我如何创建一些返回的iNode类?我会用正常的代码练习来构造这些,还是以某种方式使用Ninject?但是,如果我使用容器来创建,那么我没有给出这个图书馆对IOC的知识吗?
public interface ITopology
{
列表< INode> GetRootNodes();
}
public class TopologyImp:ITopology
{
public List< INode> GetRootNodes()
{
列表< INode> result = new List< INode>();
//这里需要代码来创建一些实例,但是如何不知道容器?
//例如想要创建一些INode实例并将它们添加到列表中,然后返回列表
}
}
public interface INode
{
//参数
long Id {get;组; }
string Name {get;组; }
}
class NodeImp:INode
{
public long Id
{
get {throw new NotImplementedException(); }
set {throw new NotImplementedException();
}
public string Name
{
get {throw new NotImplementedException(); }
set {throw new NotImplementedException(); }
}
}
//只是背景来突出显示我正在使用Ninject注入ITopology的事实
public partial class Form1:Form
{
私人ITopology _top;
public Form1()
{
IKernel kernal = new StandardKernel(new TopologyModule());
_top = kernal.Get< ITopology>();
InitializeComponent();
}
}
你正在构建一个单一的或者是那种性质的东西,并尝试注入依赖关系,通常你会将你的代码写成一个普通的类,而不用把很多(可能是错误的)代码放在管理单例中,而是注册对象 InSingletonScope
(v2 - 你没有提到你的Ninject版本)。每次你这样做,你有一个少一点的表达它的依赖。
如果你感觉特别血腥,并确定你想反对那个一般流程,Ninject给你的主要工具是 Kernel.Inject
,哪个人可以在你(或其他人)之后使用新的
d注入一个实例来注入依赖项。但是,要找到一个人的内核,你通常会使用一个服务定位器,这可能会导致很多麻烦,因为它可能会解决。
编辑:感谢您的跟进 - 我看到你的追求。 : -
///< summary>
/// Ninject中非常自动的工厂的丑陋的例子
///< / summary>
class AutomaticFactoriesInNinject
{
class Node
{
}
class NodeFactory
{
public NodeFactory(Func< ; Node> createNode)
{
_createNode = createNode;
}
Func< Node> _createNode;
public Node GenerateTree()
{
return _createNode();
}
}
内部类模块:NinjectModule
{
public override void Load()
{
绑定&FunC< ; Node>>()。ToMethod(context =>()=> Kernel.Get< Node>());
}
}
[事实]
public void CanGenerate()
{
var kernel = new StandardKernel(new Module()) ;
var result = kernel.Get&NodeFactory>()。GenerateTree();
Assert.IsType< Node>(result);
}
}
ToMethod
东西是 ToProvider
模式的特定应用程序 - 以下是通过该路线执行相同操作的方法: -
...
class NodeProvider:IProvider
{
public Type Type
{
get {return typeof(Node);
}
public object Create(IContext context)
{
return context.Kernel.Get< Node>();
}
}
内部类模块:NinjectModule
{
public override void Load()
{
绑定&FunC< ;节点>>()&ToProvider LT; NodeProvider>();
}
}
...
我没有想过这个,但不建议将它作为一个好主意 - 可能会有更好的方式来构建这样的东西。 @Mark Seemann? :P
我相信Unity和MEF也支持这方面的事情(关键字:自动工厂,Func)
编辑2:如果您愿意使用特定于容器的属性并放弃属性注入(即使Ninject允许您覆盖特定属性,我更喜欢构造函数注入),则语法较短:
class NodeFactory
{
[Inject]
public Func< Node> NodeFactory {private get;组;
public Node GenerateTree()
{
return NodeFactory();
}
}
编辑3:您还需要注意这个Ninject模块由@Remo Gloor预定在2.4发布
编辑4:同样重叠但并不直接相关的是,在Ninject中,您可以请求一个 IKernel
在您的ctor /属性中并注入(但不能直接在静态方法中工作)。
How do I handle classes with static methods with Ninject?
That is, in C# one can not have static methods in an interface, and Ninject works on the basis of using interfaces?
My use case is a class that I would like it to have a static method to create anunpopulated instance of itself.
EDIT 1
Just to add an example in the TopologyImp class, in the GetRootNodes() method, how would I create some iNode classes to return? Would I construct these with normal code practice or would I somehow use Ninject? But if I use the container to create then haven't I given this library knowledge of the IOC then?
public interface ITopology
{
List<INode> GetRootNodes();
}
public class TopologyImp : ITopology
{
public List<INode> GetRootNodes()
{
List<INode> result = new List<INode>();
// Need code here to create some instances, but how to without knowledge of the container?
// e.g. want to create a few INode instances and add them to the list and then return the list
}
}
public interface INode
{
// Parameters
long Id { get; set; }
string Name { get; set; }
}
class NodeImp : INode
{
public long Id
{
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
public string Name
{
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
}
// Just background to highlight the fact I'm using Ninject fine to inject ITopology
public partial class Form1 : Form
{
private ITopology _top;
public Form1()
{
IKernel kernal = new StandardKernel(new TopologyModule());
_top = kernal.Get<ITopology>();
InitializeComponent();
}
}
If you're building a singleton or something of that nature and trying to inject dependencies, typically you instead write your code as a normal class, without trying to put in lots of (probably incorrect) code managing the singleton and instead register the object InSingletonScope
(v2 - you didnt mention your Ninject version). Each time you do that, you have one less class that doesnt surface its dependencies.
If you're feeling especially bloody-minded and are certain that you want to go against that general flow, the main tools Ninject gives you is Kernel.Inject
, which one can use after you (or someone else) has new
d up an instance to inject the dependencies. But then to locate one's Kernelm you're typically going to be using a Service Locator, which is likely to cause as much of a mess as it is likely to solve.
EDIT: Thanks for following up - I see what you're after. Here's a hacky way to approximate the autofac automatic factory mechanism :-
/// <summary>
/// Ugly example of a not-very-automatic factory in Ninject
/// </summary>
class AutomaticFactoriesInNinject
{
class Node
{
}
class NodeFactory
{
public NodeFactory( Func<Node> createNode )
{
_createNode = createNode;
}
Func<Node> _createNode;
public Node GenerateTree()
{
return _createNode();
}
}
internal class Module : NinjectModule
{
public override void Load()
{
Bind<Func<Node>>().ToMethod( context => () => Kernel.Get<Node>() );
}
}
[Fact]
public void CanGenerate()
{
var kernel = new StandardKernel( new Module() );
var result = kernel.Get<NodeFactory>().GenerateTree();
Assert.IsType<Node>( result );
}
}
The ToMethod
stuff is a specific application of the ToProvider
pattern -- here's how you'd do the same thing via that route:-
...
class NodeProvider : IProvider
{
public Type Type
{
get { return typeof(Node); }
}
public object Create( IContext context )
{
return context.Kernel.Get<Node>();
}
}
internal class Module : NinjectModule
{
public override void Load()
{
Bind<Func<Node>>().ToProvider<NodeProvider>();
}
}
...
I have not thought this through though and am not recommending this as A Good Idea - there may be far better ways of structuring something like this. @Mark Seemann? :P
I believe Unity and MEF also support things in this direction (keywords: automatic factory, Func)
EDIT 2: Shorter syntax if you're willing to use container-specific attributes and drop to property injection (even if Ninject allows you to override the specific attributes, I much prefer constructor injection):
class NodeFactory
{
[Inject]
public Func<Node> NodeFactory { private get; set; }
public Node GenerateTree()
{
return NodeFactory();
}
}
EDIT 3: You also need to be aware of this Ninject Module by @Remo Gloor which is slated to be in the 2.4 release
EDIT 4: Also overlapping, but not directly relevant is the fact that in Ninject, you can request an IKernel
in your ctor/properties and have that injected (but that doesn't work directly in a static method).
这篇关于如何使用Ninject的静态方法处理类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!