How do I handle classes with static methods with Ninject?
dependency-injection, ninject
Solution
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).
Problem
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 an unpopulated 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(); } } ```