Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does MEF lend any value to the Singleton pattern?

Tags:

c#

singleton

mef

I am working on an MEF project to discover usage and implementation techniques. My first phase of discovery is to implement a dynamically configurable and centralized data controller. One way to customize behavior is to inherit a class I provide that enforces a singularity rule. While the Singleton pattern is much maligned in it's use, I may have found an implementation that could validate, to some degree, the pattern's struggling existence.

The Situation

Suppose a data control module (DataController) imported by the Host is intended to supply a common conduit to databases on request by sibling modules. I only need one DataController and to be composed as a module, DataController must implement IDataController. Implementation of DataProvider as the base class is purely optional; however, derivation from DataProvider will require some additional handling.

The Observations

Gathering the facts:

  • A static class cannot implement or extend abstract classes or interfaces. This fact alone eliminates the use of a static class to ensure a singular existence of a DataController.

  • A DataController implementing the Singleton pattern would ensure a singular existence per application domain. There is no restriction on the DataController; allowed to inherit the required interface to be imported and composed in the Host.

  • Given derivation of DataController, the standard implementation for the Singleton pattern may prove to be challenging in same cases. The proposed data library provides both publicly accessible classes: IDataController, and an abstract DataProvider. To ensure a single instance of the derived DataController, the implementation will require some deviation from the norm.

The Solution

At this point, the solution seems clear. Implementation of the Singleton pattern by the DataHandler base class. I am not naive enough to think that there are other ways I could do this. But here is my rough expectations on how to implement the pattern:

// DataLibrary referenced by Host
public interface IDataController
{ 
    IDataController Start();
    DbConnection CreateConnection<TDbConnection>(params string[] args)
        where TDbConnection : DbConnection, IDbConnection;
}

public abstract class DataProvider
{

    // singleton implementation
    private static IDataController dcInstance;

    protected static IDataController Instance
    {
        get{ return dcInstance; }
    }
    // ========================

    abstract IDataController CreateController();

    protected IDataController instanceController<TDataController>()
        where TDataController : IDataController, new()
    {
        return new TDataController ();
    }
}

// references DataLibrary
[Export(typeof(IDataController))]
public class DataController : DataProvider, IDataController
{
    public IDataController Start()
    {
         return CreateController();
    }

    protected override IDataController CreateController()
    {
        return instanceController<DataController>();
    }

    public SqlConnection CreateConnection(params string[] args)
    {
        // instance and return new SqlConnection 
    }
}

Keep in mind that I have been working this out - read, theorizing - and have not completed the implementation. There will most likely be some updates as I debug any issues.

Obviously, this implementation is only enforced if the DataController module inherits the abstract base class, DataProvider. Therefore, it stands to reason that we should enforce a rule of singularity to avoid abuse or misuse if the developer opts to derive a DataController from DataProvider.

All that said, I am curious if there is a more acceptable, or practical implementation than what I have devised. And, I begin to question if the Singleton pattern is the right choice. With the Singleton pattern's much maligned existence (and, for the most part, rightfully so), I should, therefore, question my choice.

Is there a more practical implementation to meet my requirements? *Is this the right implementation of the Singleton pattern in this case?* Does this implementation actually lend any value to the pattern's existence?

like image 838
IAbstract Avatar asked Dec 19 '10 19:12

IAbstract


People also ask

What is an efficient way to implement a Singleton Pattern in java?

The most popular approach is to implement a Singleton by creating a regular class and making sure it has: A private constructor. A static field containing its only instance. A static factory method for obtaining the instance.

When we use Singleton design pattern give real time example?

If in your solution some object has only one instance and you want to model that in your design then you should use singleton pattern. For example if you are modelling a PC in the software there can be only one instance of a PC with respect to your running program.

In which scenario we use Singleton Pattern?

It is used where only a single instance of a class is required to control the action throughout the execution. A singleton class shouldn't have multiple instances in any case and at any cost. Singleton classes are used for logging, driver objects, caching and thread pool, database connections.

How to initialize a Singleton?

To create a singleton class using Eager Initialization method, we need to follow the below steps: Declare the constructor of the class as private. Now, create a private class member for this Singleton class. In the next step, you need to define a factory method that will return the object of the Singleton class.


1 Answers

If you want to enforce the fact that only a single instance of a class exists in the container, then you can just set the "shared" part creation policy:

[Export(typeof(IDataController))]
[PartCreationPolicy(CreationPolicy.Shared)]
public class DataController : IDataController
{
    ...
}

Each part importing IDataController will then receive the same instance. Note that this already the default behavior in MEF if you specify no part creation policy at the import or export side.

You should not build "singletonness" into a class. Whether something is a singleton is part of the component metadata or the configuration of the container. Other dependency injection containers follow the same approach. For example, in autofac you declare something as being a singleton like this:

builder.Register(c => new DataController())
    .As<IDataController>().SingleInstance();
like image 200
Wim Coenen Avatar answered Oct 13 '22 22:10

Wim Coenen