简体   繁体   中英

Singleton with Dependency Injection

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM