如何在子类中覆盖静态的,类似工厂的方法

时间:2015-03-19 14:17:18

标签: c# generics static factory creation

问题:

基类中的静态方法无法覆盖,因此我无法编译此代码(如果可以,我的设计将得到解决):

public abstract class ParametersBase
{
    public static abstract ParametersBase CreateDefault();  // THIS DOES NOT COMPILE!
}

public abstract class ParametersXml<T> where T : ParametersBase
{
    public static T LoadOrDefault(string fname)
    {
        System.Threading.Thread.CurrentThread.CurrentCulture =
            System.Globalization.CultureInfo.InvariantCulture;

        T result;

        var serializer = new XmlSerializer(typeof(T));
        FileStream fs;

        try
        {
            using (fs = new FileStream(fname, FileMode.Open, FileAccess.Read))
                result = (T)serializer.Deserialize(fs);
        }
        catch (InvalidOperationException)
        {
            result = (T)typeof(T).GetMethod("CreateDefault").Invoke(null, new object[] { });
            using (fs = new FileStream(fname, FileMode.Create, FileAccess.Read))
                serializer.Serialize(fs, result);
        }

        return result;
    }
}

背景:

我正在尝试使用泛型在一组子类中实现简单的XML持久性,这些子类表示这些行中的参数组:

  • 每个Parameter子类都有一些属性,这些属性在子类之间有所不同;
  • 每个类都有一个静态LoadOrDefault方法和一个实例Save方法;
  • 持久性的详细信息(xml序列化和反序列化)将封装在一个类中;
  • 使用默认值的实例化将放在每个相应的类中。

我甚至不确定这些应该是正确的合作,我的意思是,每个ParameterBase都需要包裹&#34;通过ParametersXml<>,可能正确的做法是通过继承将持久性代码封装在基类中

...

这是一个好方法吗?我错过了什么吗?

1 个答案:

答案 0 :(得分:3)

只是详细说明评论中发生的事情。

static方法标记为abstract会产生编译时错误。主要是因为你不能在一般意义上将多态性应用于抽象方法(永远不会有虚拟方法调用)。

此实例需要的是不将方法标记为static。现在出现的问题是,人们无法确定是否可以获得T的实例。但是,可以通过将类定义更改为:{/ 1>进一步约束T以使构造函数不带参数来更改此值。

public abstract class ParametersXml<T> where T : ParametersBase, new()

现在catch LoadOrDefault可以说:

result = new T().CreateDefault();

注意这样做也更清晰,并且避免使用反射和脏类型转换。

编辑: 更进一步

正如@AlexeiLevenkov指出的那样 - 假设CreateDefault应该返回自己类型的实例,并且无参数构造函数在其默认状态下设置T。甚至可以完全消除CreateDefault的需要,只需将无参数构造函数用作CreateDefault,从而将catch处理程序中的行更改为:

result = new T();