C# 避免XML可序列化类中的重复代码

C# 避免XML可序列化类中的重复代码,c#,xml-serialization,dry,C#,Xml Serialization,Dry,我有两个Serializable类,它们的代码非常相似。实际上,除了调用特定构造函数的部分外,序列化代码是相同的 有没有办法创建一个包含公共部分的公共类,以便特定类(子类?)只能实现构造函数部分?我可以想到泛型,工厂模式,但不知道如何做到这一点 // Fictitious classes [Serializable] public class FlightParameters { public double MaxHeight { get; set; } pulbic dou

我有两个
Serializable
类,它们的代码非常相似。实际上,除了调用特定构造函数的部分外,序列化代码是相同的

有没有办法创建一个包含公共部分的公共类,以便特定类(子类?)只能实现构造函数部分?我可以想到泛型,工厂模式,但不知道如何做到这一点

// Fictitious classes

[Serializable]
public class FlightParameters {

    public double MaxHeight { get; set; }
    pulbic double MaxSpeedKmPerHour { get; set; }

    public static FlightParameters Load(String fname) {
        FlightParameters result;
        using (var fs = new FileStream(fname, FileMode.OpenOrCreate)) {
            var serializer = new XmlSerializer(typeof(FlightParameters));
            try {
                result = (FlightParameters)serializer.Deserialize(fs);
            }
            // catch "file not found"
            catch (InvalidOperationException) {
                result = new FlightParameters() {
                    MaxHeight = 30000;
                    MaxSpeedKmPerHour = 1500;
                }
                serializer.Serialize(fs, result);
            }
            return result;
        }
    }

}


[Serializable]
public class SailingParameters {

    public double MaxDepth { get; set; }
    pulbic double MaxSpeedKnots { get; set; }

    public static SailingParameters Load(String fname) {
        SailingParameters result;
        using (var fs = new FileStream(fname, FileMode.OpenOrCreate)) {
            var serializer = new XmlSerializer(typeof(SailingParameters));
            try {
                result = (SailingParameters)serializer.Deserialize(fs);
            }
            // catch "file not found"
            catch (InvalidOperationException) {
                result = new SailingParameters() {
                    MaxDepth = 13000;
                    MaxSpeedKnots = 15;
                }
                serializer.Serialize(fs, result);
            }
            return result;
        }
    }

}
用法:

FlightParameters _fparam = FlightParameters.Load(somePath);
SailingParameters _sparam = SailingParameters.Load(someOtherPath);

我能看到的最简单的方法是:

static class XmlUtils {
    public static T Load<T>(string filename, Func<T> onMissing = null)
        where T : class, new()
    {
        using (var fs = File.OpenRead(filename)) {
            var serializer = new XmlSerializer(typeof(T));
            try {
                return (T)serializer.Deserialize(fs);
            } catch (InvalidOperationException) { // catch "file not found"
                return onMissing == null ? new T() : onMissing();
            }
        }
    }
}
静态类XmlUtils{
公共静态T加载(字符串文件名,Func onMissing=null)
其中T:class,new()
{
使用(var fs=File.OpenRead(文件名)){
var serializer=newxmlserializer(typeof(T));
试一试{
返回(T)序列化程序。反序列化(fs);
}catch(InvalidOperationException){//catch“未找到文件”
返回onMissing==null?新的T():onMissing();
}
}
}
}
允许这样的事情

public static SailingParameters Load(string filename) {
    return XmlUtils.Load<SailingParameters>(filename, () => new SailingParameters {
        MaxDepth = 13000;
        MaxSpeedKnots = 15;
    });
}
publicstaticsailingparameters加载(字符串文件名){
返回XmlUtils.Load(文件名,()=>新的SailingParameters{
最大深度=13000;
MaxSpeedKnots=15;
});
}

实际上不显示任何构造函数;你是说加载方法吗?哦,您不需要
[Serializable]
-
XmlSerializer
根本不关心that@MarcGravell我添加了用法示例。没错,没有公共构造函数,但是可以看到在“catch”块中调用默认构造函数。我不确定我在这里做的事情是否正确,所以欢迎任何建议,包括另一种完全不同的方法。
OpenOrCreate
也可能非常有害,注意-这可能会使你的磁盘充满空文件,不是吗?@marcgravel可能是的,但在我的程序的其他地方运行一些清理例程。对于这个特定的部分,我相信
OpenOrCreate
是理想的行为。有趣!午饭后再测试一下,然后发布一些反馈@heltonbiker您甚至可能不需要
-我怀疑编译器可以从lambda-so
返回XmlUtils.Load(filename,()=>new SailingParameters{…})推断出这一点这里有一个问题:我的原始代码在catch参数中创建了一个新的默认对象,并在返回它之前将其序列化。若我返回一个返回对象的函数,那个么在返回它之前如何将其序列化到文件中?重要的是,它发生在
XmlUtils
类中,以避免重复。@helton k-只捕获创建的对象,而不是返回它;连载;然后返回