I have a very simple test project where I try tell ninject that my ILoader instance should be a singleton. No matter what I do it creates multiple instances of it.
Simple interface.
public interface ILoader
{
IEnumerable<int> Get();
}
Implementation for test purpose
public class TestLoader : ILoader
{
private IEnumerable<int> _Datasource;
public void Set(IEnumerable<int> enumerable)
{
_Datasource = enumerable;
}
public IEnumerable<int> Get()
{
return _Datasource;
}
}
Class that depends on it
public class TestClass
{
private ILoader _loader;
public TestClass(ILoader loader)
{
_loader = loader;
}
public void Init()
{
foreach (var i in _loader.Get())
Console.WriteLine(i);
}
}
Module
public class TestModule : NinjectModule
{
public override void Load()
{
Bind<ILoader>().To<TestLoader>();
Bind<TestLoader>().ToSelf().InSingletonScope();
}
}
And run it.
class Program
{
static void Main(string[] args)
{
var kernel = new StandardKernel(new TestModule());
var ds = new List<int> { 1, 2 };
kernel.Get<TestLoader>().Set(ds);
var tc = kernel.Get<TestClass>();
tc.Init();
Console.ReadLine();
}
}
Here I want to preload my loader with testdata and the ninject should inject that very same loader into my TestClass. However it creates a new instance which is not really the desired behaviour.
I guess there are ways to work around this. But then what is the purpose of InSingletonScope? Shouldnt I be able to tell ninject that I want one and only one instance of ILoader.
Instead of having the Set method, you should use constructor injection (see this question) like this:
public class TestLoader : ILoader
{
private IEnumerable<int> _Datasource;
public TestLoader(IEnumerable<int> enumerable)
{
_Datasource = enumerable;
}
public IEnumerable<int> Get()
{
return _Datasource;
}
}
And then here is how you would register it and resolve it:
static void Main(string[] args)
{
var kernel = new StandardKernel();
var ds = new List<int> { 1, 2 };
kernel
.Bind<ILoader>()
.To<TestLoader>()
.InSingletonScope()
.WithConstructorArgument("enumerable", ds);
var tc1 = kernel.Get<TestClass>();
var tc2 = kernel.Get<TestClass>();
tc1.Init();
tc2.Init();
Console.ReadLine();
}
In this example, the two instance of TestClass will get the same instance of TestLoader injected into them.
If for some reason you don't want to use constructor injection and you want to keep the Set method, you can do this:
static void Main(string[] args)
{
var kernel = new StandardKernel();
var ds = new List<int> { 1, 2 };
kernel
.Bind<ILoader>()
.To<TestLoader>()
.InSingletonScope();
((TestLoader)kernel.Get<ILoader>()).Set(ds);
var tc1 = kernel.Get<TestClass>();
var tc2 = kernel.Get<TestClass>();
tc1.Init();
tc2.Init();
Console.ReadLine();
}
Related
I want to call many tests like this.
var test8001 = new Test8001();
test8001.Execute(drv);
var test8002 = new Test8002();
test8002.Execute(drv);
var test8007 = new Test8007();
test8007.Execute(drv);
How can I automatically instantiate all test function with a int list of all test numbers?
List<int> classNameNumbers = new List<int>() { 8001, 8002, 8007 };
I need a for-loop where Execute() is called on every instance.
Edit:
The name of the type e.g. 'Test8001' should be retrieved from my integer list.
Try out the following
namespace Stackoverflow46529447
{
class Program
{
static void Main(string[] args)
{
var drv = new Drv();
var numbers = new[] {8001, 8002, 8003};
var executables = numbers.Select(x => Activator.CreateInstance(Type.GetType($"Stackoverflow46529447.Test{x:0000}")))
.OfType<IExecutable>()
.ToArray();
foreach (var executable in executables)
{
executable.Execute(drv);
}
}
}
public class Test8001 : IExecutable
{
public void Execute(Drv drv)
{
Console.WriteLine("Hello from Test 8001");
}
}
public class Test8002 : IExecutable
{
public void Execute(Drv drv)
{
Console.WriteLine("Hello from Test 8002");
}
}
public class Test8003 : IExecutable
{
public void Execute(Drv drv)
{
Console.WriteLine("Hello from Test 8003");
}
}
public interface IExecutable
{
void Execute(Drv drv);
}
public class Drv
{
}
}
This uses reflection to create instance types.
I have multiple classes that inherit from IPrint. I want to instantiate these classes using a factory but I want to maintain a single instance of each type.
Is this possible?
Please find my sample code below.
public interface IPrint
{
void DoPrint();
}
public class DigitalPrint : IPrint
{
public void DoPrint()
{
// logic
}
}
public class InkPrint : IPrint
{
public void DoPrint()
{
// logic
}
}
public class PrintFactory
{
private static IDictionary<IPrint, object> prints = new
Dictionary<IPrint, object>();
private PrintFactory()
{
}
public static IPrint GetPrint(PrintType type)
{
// return instance depending on type. Instantiate only once
//like singleton
// How to write so that it returns a single instance depending
//on type
return null;
}
}
public enum PrintType
{
DigitalPrint,
InkPrint
}
Can someone give me some idea if this is possible?
Thanks.
You can create IPrint instances when initializing Dictionary<PrintType, IPrint>:
private static IDictionary<PrintType, IPrint> prints =
new Dictionary<PrintType, IPrint> {
{ PrintType.DigitalPrint, new DigitalPrint() },
{ PrintType.InkPrint, new InkPrint() }
};
Getting print (thus print is a class, the same instance will be returned for each request):
public static IPrint GetPrint(PrintType type)
{
IPrint print;
if (!prints.TryGetValue(type, out print))
return null;
return print;
}
If you don't want to create IPrint instances until the client asks for them, you can use Dictionary<PrintType, Lazy<IPrint>>:
private static IDictionary<string, Lazy<IPrint>> prints =
new Dictionary<string, Lazy<IPrint>> {
{ PrintType.DigitalPrint, new Lazy<IPrint>(() => new DigitalPrint()) },
{ PrintType.InkPrint, new Lazy<IPrint>(() => new InkPrint()) }
};
Getting print (in this case only one instance of each IPrint type will be created, but not before someone tries to get the instance of that type):
public static IPrint GetPrint(PrintType type)
{
Lazy<IPrint> factory;
if (!prints.TryGetValue(type, out factory))
return null;
return factory.Value;
}
Though I would consider using dependency injection framework instead of implementing such functionality manually.
Further reading: Ninject or Autofac
Yes, it's possible.
This creates the IPrint's before they're needed. You could make them lazily created, instead.
public class Program
{
public static void Main(string[] args)
{
var factory = new PrintFactory();
Console.WriteLine(PrintFactory.GetPrint(PrintType.DigitalPrint));
Console.WriteLine(PrintFactory.GetPrint(PrintType.InkPrint));
}
}
public interface IPrint
{
void DoPrint();
}
public class DigitalPrint : IPrint
{
public void DoPrint()
{
// logic
}
}
public class InkPrint : IPrint
{
public void DoPrint()
{
// logic
}
}
public class PrintFactory
{
// Make the dictionary from PrintType to IPrint instead of IPrint to object
private static IDictionary<PrintType, IPrint> prints = new Dictionary<PrintType, IPrint>();
// Initialize prints in a static constructor.
static PrintFactory()
{
prints.Add(PrintType.DigitalPrint, new DigitalPrint());
prints.Add(PrintType.InkPrint, new InkPrint());
}
public static IPrint GetPrint(PrintType type)
{
if (!prints.ContainsKey(type))
{
// TODO: Maybe throw an exception or log?
}
return prints[type];
}
}
public enum PrintType
{
DigitalPrint,
InkPrint
}
I would get rid of the enum and make a generic method:
public static IPrint GetPrint<T>() where T : IPrint, new ()
{
foreach (var key in prints.Keys) {
if (key is T)
return null;
}
return new T();
}
Iam currently refactoring a application and want to introduce MEF.
The Export class (class Apple) is finished and marked with Export-keyword...
On the import site I currently have a dictionary which is initialized as shown below:
Dictionary<int, Apple> dict = new Dictionary<int, Apple>();
for(int i=0; i < 10; i++)
dict.add(i, new Apple());
...
How can I initialize the dictionary using MEF?
So I think your question boils down to, "How to I ensure that the container produces multiple instances of an object rather than reusing the same object every time it's requested." Well that's pretty easy–you just have to specify CreationPolicy.NonShared.
Consider this example implementation of IApple:
public interface IApple { }
[PartCreationPolicy(CreationPolicy.NonShared)]
[Export(typeof(IApple))]
public class Apple : IApple
{
private static int appleCounter = 0;
private int id;
public Apple()
{
this.id = ++appleCounter;
}
public override string ToString()
{
return "Apple #" + this.id.ToString();
}
}
Here's one way that you might use it:
class Program
{
public static void Main(string[] args)
{
var catalog = new ApplicationCatalog();
var container = new CompositionContainer(catalog);
IDictionary<int, IApple> dict = new Dictionary<int, IApple>();
for (int i = 0; i < 10; i++)
{
dict.Add(i, container.GetExportedValue<IApple>());
}
foreach (var pair in dict)
{
Console.WriteLine("{0}: {1}", pair.Key, pair.Value);
}
}
}
The key line of code here is [PartCreationPolicy(CreationPolicy.NonShared)]. Without this, the only one Apple would ever be created. Of course this isn't quite as useful as you're probably hoping for. Here's another way to generate a dictionary that's a bit more flexible:
public interface IBasket
{
IDictionary<int, IApple> GetAppleDictionary();
}
[Export(typeof(IBasket))]
public class Basket : IBasket
{
private IDictionary<int, IApple> dict;
[ImportingConstructor]
public Basket([Import] CompositionContainer container)
{
this.dict = new Dictionary<int, IApple>();
for (int i = 0; i < 10; i++)
{
this.dict.Add(i, container.GetExportedValue<IApple>());
}
}
public IDictionary<int, IApple> GetAppleDictionary()
{
return dict;
}
}
class Program
{
[Import(typeof(IBasket))]
private IBasket basket = null;
public static void Main(string[] args)
{
var program = new Program();
program.Run();
}
private void Run()
{
var catalog = new ApplicationCatalog();
var container = CreateCompositionContainer(catalog);
container.ComposeParts(this);
foreach (var pair in this.basket.GetAppleDictionary())
{
Console.WriteLine("{0}: {1}", pair.Key, pair.Value);
}
}
private static CompositionContainer CreateCompositionContainer(ComposablePartCatalog catalog)
{
var wrappedCatalog = new AggregateCatalog(catalog, new TypeCatalog(typeof (CompositionContainer)));
var container = new CompositionContainer(wrappedCatalog);
container.ComposeExportedValue(container);
return container;
}
}
The tricky part here is CreateCompositionContainer. This method ensures that the the CompositionContainer itself can be used to satisfy an import on an object it's composing. This allows the Basket to directly manipulate the container to generate all the apples it needs.
And just for the purpose of demonstration, here's one way you could also use the [ImportMany] attribute to accomplish something similar (although all those [Export]'s really make me cringe):
public interface IApple { }
[PartCreationPolicy(CreationPolicy.NonShared)]
[Export(typeof(IApple))]
[Export(typeof(IApple))]
/* ..repeat N times.. */
[Export(typeof(IApple))]
public class Apple : IApple
{
private static int appleCounter = 0;
private int id;
public Apple()
{
this.id = ++appleCounter;
}
public override string ToString()
{
return "Apple #" + this.id.ToString();
}
}
class Program
{
[ImportMany(typeof(IApple))]
private IEnumerable<IApple> apples = null;
public static void Main(string[] args)
{
var program = new Program();
program.Run();
}
void Run()
{
var catalog = new AssemblyCatalog(this.GetType().Assembly);
var container = new CompositionContainer(catalog);
container.ComposeParts(this);
apples.Dump();
}
}
Let's say that I have a class called DataService in my client app. This class have many methods which make calls to a WCF service.
I wonder which is a better practice:
To create an instance of WebServiceClient in the class, which is initialized when an instance of the class is created, and is used by the methods, e.g:
public class DataService
{
MyWebServiceClient client = new MyWebServiceClient();
public void Method1()
{
var v = client.Operation1();
...
}
public void Method2()
{
var v = client.Operation2();
...
}
}
Or, to create and initialize an instance of WebServiceClient in each method of the class, e.g:
public class DataService
{
public void Method1()
{
var client = new MyWebServiceClient();
var v = client.Operation1();
...
}
public void Method2()
{
var client = new MyWebServiceClient();
var v = client.Operation2();
...
}
}
There is also a third option, which is to declare in class and initialize in each method:
public class DataService
{
MyWebServiceClient client;
public void Method1()
{
client = new MyWebServiceClient();
var v = client.Operation1();
...
}
public void Method2()
{
client = new MyWebServiceClient();
var v = client.Operation2();
...
}
}
When you have a dependency on another class like this, its usually a good idea to separate out its construction and pass it in (or possibly use dependency injection). This makes your DataService class easier to test, you can more easily mock your WebServiceClient this way.
consider something like...
public class DataService
{
public DataService(MyWebServiceClient client)
{
.... //Assign it to a private var...
}
}
I would use Constructor injection and one instance per class as in:
public class DataService
{
IMyWebServiceClient _client;
public DataService(IMyWebServiceClient client)
{
_client=client
}
public DataService():this(new MyWebServiceClient())
{
}
public void Method1()
{
var v = _client.Operation1();
...
}
public void Method2()
{
var v = _client.Operation2();
...
}
}
I have used method 3 most often in older applications. But recently have seen some code where you have object declaration but instantiation is done by some framework like Spring. The instance is kept inside container. Still learning about that process though.
public class DataService
{
MyWebServiceClient client;
public void Method1()
{
var v = client.Operation1();
...
}
public void Method2()
{
var v = client.Operation2();
...
}
}
I am using the following interface as a ToFactory() binding:
public interface ISamplerFactory
{
ISampler Create(Action<EventHandler<ValueChangedEventArgs>> register, Action<EventHandler<ValueChangedEventArgs>> unregister, Func<decimal?> valueGetter);
}
When I bind ToFactory() I can successfully create the class but I then get a memory leak whereby the register, unregister and valueGetter parameters are held by a ConstructorArgument inside Ninject, which reference a target/parameter object inside the delegates. This keeps that target object from getting GC'd. I am using ContextPreservation extension too if that makes a difference. (See complete sample code below)
When I remove the "ToFactory()" bind and create a standard factory class, it works.
public class SamplerFactory : ISamplerFactory
{
private readonly IDistributionResolver _resolverFactory;
public SamplerFactory(IDistributionResolverFactory resolverFactory)
{
_resolverFactory = resolverFactory;
}
ISampler Create(Action<EventHandler<ValueChangedEventArgs>> register, Action<EventHandler<ValueChangedEventArgs>> unregister, Func<decimal?> valueGetter)
{
return new SpecificSampler(_resolverFactory, register, unregister, valueGetter);
}
}
And my target objects inside the delegates are GC'd successfully.
Is there something I am doing wrong or isn't the Factory extension meant to handle these more complex arguments? I assume if I used the .WithConstructorArgument I would get the same outcome.
EDIT: Added all necessary bindings and rewrote my sample code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication
{
using System;
using Ninject;
using Ninject.Extensions.ContextPreservation;
using Ninject.Extensions.Factory;
public class Program
{
static void Main(string[] args)
{
new Program().Run();
}
public void Run()
{
var kernel = new StandardKernel(new NinjectSettings() { LoadExtensions = false });
kernel.Load(new FuncModule());
kernel.Load(new ContextPreservationModule());
kernel.Bind<IDistributionResolver>().To<DistributionResolver>(); // This is a constructor-less object.
kernel.Bind<ISampler>().To<SpecificSampler>();
kernel.Bind<ISamplerFactory>().ToFactory();
kernel.Bind<IInjected>().To<Injected>();
kernel.Bind<IDistributionResolver>().To<DistributionResolver>();
kernel.Bind<IDistributionResolverFactory>().ToFactory();
var s = new SomeObject();
var weakS = new WeakReference(s);
var factory = kernel.Get<ISamplerFactory>();
var sampler = CreateInstance(factory, s);
s = null;
factory = null;
sampler = null;
GC.Collect();
if (weakS.IsAlive)
throw new Exception();
}
private ISampler CreateInstance(ISamplerFactory factory, SomeObject someObject)
{
var x = factory.Create(y => someObject.Do += y, z => someObject.Do -= z, () => someObject.Query());
if (x == null)
throw new Exception();
return x;
}
public class SomeObject
{
public event EventHandler<ValueChangedEventArgs> Do;
public decimal? Query()
{
return 0;
}
}
public class SpecificSampler : ISampler
{
private readonly IDistributionResolverFactory resolver;
private readonly Action<EventHandler<ValueChangedEventArgs>> register;
private readonly Action<EventHandler<ValueChangedEventArgs>> unregister;
private Func<decimal?> _valueGetter;
public SpecificSampler(
IDistributionResolverFactory resolver, // This is injected
Action<EventHandler<ValueChangedEventArgs>> register, // The rest come from the factory inputs
Action<EventHandler<ValueChangedEventArgs>> unregister,
Func<decimal?> valueGetter)
{
this.resolver = resolver;
this.register = register;
this.unregister = unregister;
_valueGetter = valueGetter;
// Do Stuff;
}
}
public class ValueChangedEventArgs : EventArgs
{
}
public interface ISamplerFactory
{
ISampler Create(Action<EventHandler<ValueChangedEventArgs>> register, Action<EventHandler<ValueChangedEventArgs>> unregister, Func<decimal?> valueGetter);
}
public interface IDistributionResolverFactory
{
IDistributionResolver Create(IDictionary<string, string> picked);
}
public interface IDistributionResolver
{
}
private class DistributionResolver : IDistributionResolver
{
readonly IInjected _i;
readonly IDictionary<string, string> _picked;
public DistributionResolver(IInjected i, IDictionary<string, string> picked)
{
_i = i;
_picked = picked;
}
}
public interface ISampler
{
}
}
public interface IInjected
{
}
class Injected : IInjected
{
}
}
I tracked this down to a memory leak in Ninject Core:
https://github.com/ninject/ninject/issues/74