Aliasgar Rajpiplawala
Aliasgar Rajpiplawala

Reputation: 656

Use singleton with Dependency Injection (Castle Windsor)

I have created a project to understand windsor castle and singleton. To achieve this I have the following code

Controller:

public class AdminController : Controller
{
    private readonly IOfflineUserService _offlineUser; 
    public AdminController()
    {
        _offlineUser = OfflineUserService.instance;
    }
    [OutputCache(Duration = 20, VaryByParam = "none", Location = OutputCacheLocation.Server, NoStore = true, SqlDependency = "Default:Admin")]
    public ActionResult test()
    {
        var data = _offlineUser.GetAllOfflineUsers();
        return View(data);
    }
}

Singleton Base Class:

    public abstract class SingletonBase<T> where T : class
    {
    #region Members

    /// <summary>
    /// Static instance. Needs to use lambda expression
    /// to construct an instance (since constructor is private).
    /// </summary>
    private static readonly Lazy<T> sInstance = new Lazy<T>(() => CreateInstanceOfT());

    #endregion

    #region Properties

    /// <summary>
    /// Gets the instance of this singleton.
    /// </summary>
    public static T Instance { get { return sInstance.Value; } }

    #endregion

    #region Methods

    /// <summary>
    /// Creates an instance of T via reflection since T's constructor is expected to be private.
    /// </summary>
    /// <returns></returns>
    private static T CreateInstanceOfT()
    {
        return Activator.CreateInstance(typeof(T), true) as T;
    }

    #endregion
}

Service Class:

  public class OfflineUserService : SingletonBase<OfflineUserService>,IOfflineUserService
{

    private readonly IUnitOfWork _unitOfWork;
    private readonly IUserRepository _userRepository;
           private readonly IAdminRepository _adminRepository;

    public OfflineUserService()
    {

    }

    public OfflineUserService(IUnitOfWork unitOfWork,
        IUserRepository userRepository,
        IAdminRepository adminRepository,
        )
    {
        _adminRepository = adminRepository;
        _unitOfWork = unitOfWork;
        _userRepository = userRepository;

    }
     public List<OfflineUsers> GetAllOfflineUsers()
    {
    //Some Code
    }
}

So in the controller instead of passing OfflineUserService.instance; I want to pass IOfflineUserService.instance so that I can use it. I don't know how to achieve this. Dependency injection is working fine if I pass it through constructor

   public AdminController(IOfflineUserService offlineUser)
    {
        _offlineUser = offlineUser;
    }

but as I want to use singleton so to achieve this I can create the instance as mention in the code but I don't know how to create the singleton instance of an interface. Please suggest if I am doing anything wrong as I am trying to understand the behavior so that I can start using it in Projects.

Upvotes: 2

Views: 6049

Answers (2)

Crixo
Crixo

Reputation: 3070

Sorry, but It seems you are doing something very wrong...

When you hire an IoC container in your project you have let him doing its job: creating instance, any instance have to create/released through the container(RRR pattern). No exception(of course data/model classes are excluded since are not even registered in the container).

In your case, you don't need the SingletonBase: the container will do the job for you. You simply have to register your component OfflineUserService and tell to the container that has to be managed as a Singleton

container.Register(
Component
.For<IOfflineUserService>()
.ImplementedBy<OfflineUserService>()
.LifestyleSingleton())

Beware you are making a very bad hierarchy error in your sample:

Your service(OfflineUserService) depends on an other component which is a UnitOfWork, that usually should have a PerWebRequest lifestyle(in a web app). If OfflineUserService will be threated a Singleton, UnitOfWork instance ends up to be a "singleton" as well... that's gonna be your worst nightmare as soon as you put your code in prod :)

Upvotes: 6

Mukesh Modhvadiya
Mukesh Modhvadiya

Reputation: 2178

Try if you can create your interface with property to get instance like this :

public interface IOfflineUserService<T> where T : class
{
    T GetServiceInstance { get; }
}

And while implementing in your class return the instance through this property :

public class OfflineUserService : SingletonBase<OfflineUserService>,IOfflineUserService<OfflineUserService>
{
    public OfflineUserService GetServiceInstance
    {
        get {
                return Instance;
            }  
    }
}

Then you can access it in controller with dependency injection.

Upvotes: 0

Related Questions