本文介绍了如何使用Ninject的静态方法处理类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



也就是说,在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 newd 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的静态方法处理类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-05 21:35
查看更多