I decided to use singleton in order to load some file when the application started and use this configuration throughout the app lifetime as this file is changed once in a year. There is a singleton:
public class Singleton
{
private static IReader reader;
private Singleton(IReader reader)
{
Singleton.reader = reader;
}
private static readonly Lazy<Dictionary<string, HashSet<string>>> lazy =
new Lazy<Dictionary<string, HashSet<string>>>(() => reader.ReadData("config") );
public static Dictionary<string, HashSet<string>> Instance { get { return lazy.Value; } }
}
And on Appstart I have:
IWindsorContainer container = new WindsorContainer();
container.Install(FromAssembly.This());
And on WindsorInstaller I have:
public class WindsorInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Component.For<IReader>().ImplementedBy<MyReader>());
}
}
My reader class is following:
public class MyReader : IReader
{
public Dictionary<string, HashSet<string>> ReadData(string source)
{
/*some code*/
return dict;
}
}
It seems that there is no injection happening on Singleton and reader is null and I get error: Object reference not set to an instance of an object. Can you please suggest what I am doing wrong and how to do it better (probably not use singleton at all)?
Your concept of the singleton with dependency injection is a bit skewed if the intention is to use it with a container yet still use statics.
Plus your class has a private
constructor. How is the container suppose to explicitly inject dependencies into a private constructor?
Construct the interface/abstraction of the intended singleton.
public interface ISingleton {
Dictionary<string, HashSet<string>> Instance { get; }
}
and implementation...
public class Singleton: ISingleton {
private readonly Lazy<Dictionary<string, HashSet<string>>> lazy;
public Singleton(IReader reader) {
this.lazy = new Lazy<Dictionary<string, HashSet<string>>>(() => reader.ReadData("config") );
}
public Dictionary<string, HashSet<string>> Instance { get { return lazy.Value; } }
}
You then register it with the container as a singleton
public class WindsorInstaller : IWindsorInstaller {
public void Install(IWindsorContainer container, IConfigurationStore store) {
container.Register(Component.For<IReader>().ImplementedBy<MyReader>());
container.Register(Component.For<ISingleton>().ImplementedBy<Singleton>().LifestyleSingleton());
}
}
Any class that has ISingeton
as a dependency will get the same instance injected when requested and the Singleton implementation will get its dependency when being resolved.