简体   繁体   中英

Singleton pattern for a property in c#

I am trying to adapt singleton policy for my CsvConfiguration Property.

If the configuration is already available, just return the configuration. else, get the configuration and return the same and I am able to build this code.

    public Rootpdf pdfConfiguration
    {
        get
        {
            Rootpdf pdfConfiguration = null;
            try
            {
                if (pdfConfiguration == null)
                {
                    //retrieve the configuration file.
                    //load the configuration and return it!
                }
                else
                {
                    return pdfConfiguration;
                }
            }
            catch (Exception e)
            {
                Log.Error("An error occurred while reading the configuration file.", e);
            }

            return pdfConfiguration;
        }
    }

Advantages (i hope): Whenever my pdfConfiguration is wanted, if already it is available, i can return it. Need not load the configuration file eachtime and calculate the configuration.

My Query: The resharper! The resharper tells that the code

   if (pdfConfiguration == null) //The expression is always true.

Is it really a problem with resharper that it doesn't understand I am following this singleton pattern ?

or

Am I not following singleton pattern at all?

You're setting the singleton to null at the top of your get clause:

Rootpdf pdfConfiguration = null;
//THIS IS THE PROBLEM.

Note: 99% of the time, ReSharper is smarter than you. I don't like it, but it's true.

think you have to use a local variable out of the getter

    private static Rootpdf  _pdfConfiguration ;
    public static Rootpdf pdfConfiguration
    {
        get
        {
            try
            {
                if (_pdfConfiguration == null)
                {
                    //retrieve the configuration file.
                    //load the configuration and return it!
                }
                else
                {
                    return _pdfConfiguration;
                }
            }
            catch (Exception e)
            {
                Log.Error("An error occurred while reading the configuration file.", e);
            }

            return _pdfConfiguration;
        }
    }

and as you want a singleton, i made it a static property... hope it's what you need.

Here is what your class should look like:

public class RootPdf
{
    private static RootPdf instance;

    private RootPdf()
    {
        //retrieve the configuration file.
        //load the configuration and return it! 
    }

    public static RootPdf Instance
    {
        get
        {
            if (instance == null)
            {
                try
                {
                    instance = new RootPdf();
                }
                catch (Exception e)
                {
                    Log.Error("An error occurred while reading the configuration file.", e);
                    return null;
                }
            }
            return instance;
        }
    }
}

And here is how you will call the object:

var pdf = RootPdf.Instance;

This line: if (pdfConfiguration == null) will always be true due to this line (just before) Rootpdf pdfConfiguration = null; . What you need to do is to place the last line ( Rootpdf pdfConfiguration = null; ) outside the Get method. This will stop the variable to be initialized to null each time.

private static Rootpdf pdfConfiguration = null;
public Rootpdf PdfConfiguration
{

    get
    {            
        try
        {
            if (pdfConfiguration == null)
    ....

More information on the Singleton Pattern is available here .

Alternatively, you can use a Static Constructor :

A static constructor is used to initialize any static data, or to perform a particular action that needs to be performed once only. It is called automatically before the first instance is created or any static members are referenced.

public class Foo {
private static Rootpdf pdfConfiguration = null;
static Foo()
{
    pdfConfiguration = ....
}
public Rootpdf pdfConfiguration
{
    get
    {
        return pdfConfiguration;
    }
 ....
class MySingletonClass 
{
    private static UserSettings instance = null;

    /// <summary>
    /// Default protected constructor.
    /// </summary>
    protected MySingletonClass()
    {
    }

    /// <summary>
    /// Invoke the singleton instance.
    /// </summary>
    public static MySingletonClass Instance()
    {
        if (instance == null)
            instance = new MySingletonClass();
        return instance;
    }
}

This woud be invoked/instanciated like

MySingletonClass msc = MySingletonClass.Instance();

You can also use an accessor/Property to return the instance

public MySingletonInstance Instance
{
    get 
    {
        if (instance == null)
            instance = new MySingletonInstance();
        return instance;
    }
}

Where this is invoked/instantiated via

MySingletonClass msc = MySingletonClass.Instance;

I like the first method of the above.

I hope this helps.

As already mentioned this is a not a singleton pattern.

If you want to stick with the idea you described then I would change your code to :

internal class Config
    {
        private readonly Lazy<Rootpdf> _config;
        public Config()
        {
            _config = new Lazy<Rootpdf>(ReadConfiguration);
        }

        private Rootpdf ReadConfiguration()
        {
            throw new NotImplementedException();
        }


        public Rootpdf pdfConfiguration
        {
            get
            {                
                try
                {
                    return _config.Value;
                }
                catch (Exception e)
                {
                    Log.Error("An error occurred while reading the configuration file.", e);
                }

                return null;
            }
        }

Nowadays , I think since C# 6.0, you can use initial values with properties, like this:

static public Rootpdf pdfConfiguration { get; } = new Func<Rootpdf>(() => {
    //retrieve the configuration file.
    //load the configuration and return it!
    return new Rootpdf();   // Something like this perhaps..?
})();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM