简体   繁体   中英

Implementation Problem with Static Sealed Class

I have a Sealed class in C#, which already exists and all methods are static. It does some file operations with xml file. The file name till today was hardcoded into source. Now the requirement needs to keep it in Configuration file.

The problem is: Since class is extract, i need to expose some static 'Initialize' method to assign filename to some local static filename variable, which will replace hardcoded string. So, i always have to make sure, Initialize is called first and then later method. So, the better way is to have constructor, which i cant write.

I want a better way to do this ensuring type safety.

If the filename field is static, you could make it a property or method and make sure the getter does the work of initializing it from the configuration file if it is not already initialized...

That way you don't have to explicitly initialize the class via a method you can have the access to the property itself initialize the value.

Something like below..

static string FileName { get { return (_field ?? _field = GetFileName()); } }

static string GetFileName() { /* TODO: Return filename from config */ }

Why can't you use a static constructor?

You could write a static constructor to initialize your paths before the static members are referenced.

More info can be found here

If the class itself doesn't know how to access the config I'd use a one time setter:

private static string _filename;
public static string Filename
{
  get
  {
    if(_filename==null)
      throw new InvalidOperationException("Filename not set");
    return _filename;
  }
  set
  {
    if(_filename!=null)
      throw new InvalidOperationException("Filename set twice");
    _filename=value;
  }
}

Or if the class can access the config directly it's even easier:

private static readonly string Filename;
static MyClassName()
{
  Filename=GetFilenameFromConfig();
}

Just initialize it in a static constructor.

假设配置文件路径是已知的(即该类不接受任何形式参数),则静态构造函数可能会有所帮助。

You could change your current class from something like:-

public static Foo
{
    public static void Execute()
    {
        const string FileName = "foo.xml";
        // ...
    }
}

To something like

public static Foo
{
    public static void Execute()
    {
        Execute("foo.xml");
    }

    public static void Execute(string fileName)
    {
        // ...
    }
}

Current clients of the code can continue to use the original method (hard coded file name) and any new clients which have the file name as a configuration item can use the new method which takes the file name as a parameter. Or, if you have decided that all client should use the new method, then you can change them to do that and remove the old method.

The simplest option would be to add a static constructor. That will be executed before any other code:

public static class Foo
{
    static Foo()
    {
        // Initialization code
    }

    // Other methods which can depend on initialization code having run
}

As I say, this is the simplest - in terms of changes to your existing code. However, code like this tends to be hard to debug, and if you have a lot of static constructors which depend on each other, you can get into some tricky situations (particularly if you have cyclic dependencies). For an example of this, watch the "C# Puzzlers" video from NDC 2010 - an excellent talk given by Eric Lippert and Neal Gafter.

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