There seems to be stigma regarding the use of singletones. I never personally bought into it, but for the sake of an open mind, I try to give the IoC concept a try as an alternative, because I am frankly bored of my daily work and I want to try something else. Forgive me if my interpretation of IoC concepts is wrong or wrong.
Here's the situation: I'm HttpListener
based web server in a Windows service that uses a plug-in model to determine how to process a request based on the requested URL (like everyone else who asks about the HttpListener
). My approach to opening plugins is to request a customized directory for assemblies decorated with HttpModuleAssemblyAttribute
. These assemblies can contain 0 or more IHttpModule
children, which are additionally decorated with the HttpModuleAttribute
used to indicate the module name, version, human-readable description, and other information. Something like:
[HttpModule()] public class SimpleHttpModule : IHttpModule { public void Execute(HttpListenerContext context) { } }
When an HttpModule
detected HttpModule
I usually add it to the Dictionary<string, Type>
object, whose sole purpose is to keep track of which modules we know. This dictionary, as a rule, lives in my diversity of Singleton, which takes on the character ACE Singleton Style (a legacy from my C ++ days, where I learned about singletones).
Now what I'm trying to implement is something similar, using (my understanding) the general concepts of IoC. Basically, I have a collection of AppService
, where IAppService
is defined as:
public interface IAppService : IDisposable { void Initialize(); }
And my AppService
plugin will look something like this:
[AppService("Plugins")] internal class PluginAppService : IAppService, IDictionary<string, Type> { internal Type Item(string modName) { Type modType; if (!this.TryGetValue(modName, out modType) return null; return modType; } internal void Initialize() {
Then, during the OnStart
service, I create an instance of AppServices
, which is locally known, but passed to the constructor of all installed plugins:
public class AppServices : IDisposable, IDictionary<string, IAppService> { public void Initialization() {
Our implementation of one single method becomes an abstract implementation + constructor for a child:
[HttpModule(/*Some property values that matter */)] public abstract class HttpModule : IHttpModule { protected AppServices appServices = null; public HttpModule(AppServices services) { appServices = services; } public abstract void Execute(HttpListenerContext context); } [HttpModule()] public class SimpleHttpModule : HttpModule { public SimpleHttpModule(AppServices services) : base(services) { } public override void Execute(HttpListenerContext context) { } }
And any access to commonly used application services becomes:
var plugType = appServices["Plugins"][plugName];
but not:
var plugType = PluginManager.Instance[plugName];
I skipped some basic IoC concepts here that would simplify this all or is this really an advantage for all this extra code? In my world, Singletons are simple creatures that allow code through the entire program to access the necessary (relatively static) information (in this case, they are types).
To ask questions in more detail:
- Is this a valid version of Factory Singleton translated into IoC / DI concepts?
- If so, where is the payback / benefit for additional code and the imposition of a seemingly more awkward API?