C# – Use singleton with Dependency Injection (Castle Windsor)

asp.net-mvc-4ccastle-windsorsingleton

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.

Best Answer

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 :)

Related Topic