none
Rebind Singleton C# RRS feed

  • Question

  • I have a class library with singleton as following

    public class CoreService { private static readonly Lazy<CoreService> lazy = new Lazy<CoreService>(() => new CoreService()); public static CoreService Instance { get { return lazy.Value; } } public ISender MailSender; public CoreService( ) { } }

    I sender is implemented by two classes one for production and one for testing and as this is wcf class, and I use topshelf for hosting, it will be hard to use a contractor with parameters. so how to inject the interface on runtime 





    • Edited by aabdellatif Thursday, November 22, 2018 2:25 PM
    Thursday, November 22, 2018 2:18 PM

All replies

  • What does "two classes one for production and one for testing" mean? Can you rephrase your question?

    See Misko Hevery's talk: The Clean Code Talks - "Global State and Singletons"

    Btw, your code snippet is not a proper implementation of the Singleton pattern. This requires that the ctor is private.

    Thursday, November 22, 2018 4:08 PM
  • I would still pass the interface as a parameter to the constructor. The problem, in my opinion, is that you need to adjust how you create your object. The code that has the dependency should be pushed down a layer such that your WCF service consumes the type that has the dependency. If this is the only case where you need dependency injection then I'd build it into the code. If you need flexibility or this elsewhere then I'd consider looking for a DI container that supports Windows services.

    For the simplest approach without a formal DI or any other dependencies let the startup code figure it out.

    public abstract class CoreService
    {
       public CoreService ( ISender mailSender )
       { … }
    }
    
    //Use poor man's DI for this one case
    public class FakeCoreService : CoreService
    {
       public FakeCoreService () : base(new FakeSender())
       { }
    }
    
    public class RealCoreService : CoreService
    {
       public RealCoreService () : base(new RealSender())
       { }
    }
    
    //Looks like you're hosting WCF in a Windows service...
    void Main ( string[] args )
    {
       var useFake = //Figure out whether you're testing or not
       var service = useFake ? new FakeCoreService() : new RealCoreService();
       ...
    }
    
    If that is not going to work out for you then you can also use a factory to create the appropriate instance (with parameters) based upon the settings. A factory is useful when you need to call a single method to set up a potentially complex object. 


    Michael Taylor http://www.michaeltaylorp3.net

    Thursday, November 22, 2018 4:17 PM
    Moderator