以通用方式调用静态方法

时间:2016-05-23 20:40:03

标签: c# inheritance static-methods

我有多个类,如:

public class Base { }
public class Base1: Base { public static List<Base1> LoadFromXml(string path) }
public class Base2: Base { public static List<Base2> LoadFromXml(string path) }

然后我想要一个像这样的方法:

public List<T> PrepareBase<T>() where T: Base { return T.Load("C:\test.xml"); }

因此我不必为每种类型制作方法。 但我不知道如何完成这个或类似的东西。

问题是我不能让基类知道LoadFromXml方法,因为静态继承不是一个东西。也没有用静态方法创建单独的接口。

有没有办法做到这一点,还是我期待太多?

编辑: LoadFromXml方法的一个示例:

public class Base1 
{
    public int ID { get; set; }
    public string PropertyOnlyInBase1 { get; set; }
    public static List<Base1> LoadFromXml(string path)
    {
        List<Base1> baseList = new List<Base1>();
        XDocument doc = XDocument.Load(path);
        foreach(var node in doc.Descendants("Base1"))
        {
            Base 1 base = new Base1() { ID = node.Attributes["id"] };
            base.PropertyOnlyInBase1 = node.Element("PropertyOnlyInBase1");
            baseList.Add(base);
        }
        return baseList;
    }
}

因此Base类也有一些独特的属性。这就是为什么我首先需要继承的东西。

3 个答案:

答案 0 :(得分:1)

一种选择是添加GenericBase

public abstract class Base
{
}
public static class GenericBase<T>
    where T : Base
{
    public static List<T> LoadFromXml(string path)
    {
        //Load from XML
    }
}
public class Base1 : Base { }
public class Base2 : Base { }

public class Test //MainForm.cs class or whatever you want
{
    public void Tester() //Load event handler or whatever you want
    {
        List<Base1> base1List = PrepareBase<Base1>();
    }
    public List<T> PrepareBase<T>() where T : Base
    { return GenericBase<T>.LoadFromXml("C:\test.xml"); }
}

修改

D Stanley所述,这是不可能的;但我做了一些可能对你有所帮助的解决办法:

public abstract class Base
{
    public static List<T> LoadFromXml<T>(string path) where T : Base, new()
    {
        List<T> baseList = new List<T>();
        XDocument doc = XDocument.Load(path);
        foreach (var node in doc.Descendants(typeof(T).Name))
        {
            T t = new T();
            Dictionary<string, string> d = new Dictionary<string, string>();
            foreach (var item in node.Elements())
                d.Add(item.Name.ToString(), item.Value);
            t.Load(d);
            baseList.Add(t);
        }
        return baseList;
    }

    protected internal abstract void Load(Dictionary<string, string> elements);
}
public class Base1 : Base
{
    public string CustomProp1 { get; set; }
    public string CustomProp2 { get; set; }
    public string CustomProp3 { get; set; }

    protected internal override void Load(Dictionary<string, string> elements)
    {
        if (elements.ContainsKey("CustomProp1"))
            CustomProp1 = elements["CustomProp1"];
        if (elements.ContainsKey("CustomProp2"))
            CustomProp2 = elements["CustomProp2"];
        if (elements.ContainsKey("CustomProp3"))
            CustomProp3 = elements["CustomProp3"];
    }
}
public class Base2 : Base
{
    public string CustomProp1 { get; set; }
    public string CustomProp2 { get; set; }
    public string CustomProp3 { get; set; }
    protected internal override void Load(Dictionary<string, string> elements)
    {
        if (elements.ContainsKey("CustomProp1"))
            CustomProp1 = elements["CustomProp1"];
        if (elements.ContainsKey("CustomProp2"))
            CustomProp2 = elements["CustomProp2"];
        if (elements.ContainsKey("CustomProp3"))
            CustomProp3 = elements["CustomProp3"];
    }
}

public class Test //MainForm.cs class or whatever you want
{
    public void Tester() //Load event handler or whatever you want
    {
        List<Base1> base1List = PrepareBase<Base1>();
    }
    public List<T> PrepareBase<T>() where T : Base, new()
    {
        return Base.LoadFromXml<T>("C:\test.xml");
    }
}

答案 1 :(得分:0)

我认为从XML加载这些类的类应该与加载的类分开是正确的。正如你所说,它与实例没有真正的联系。

也许您需要的是一个单独的类来为您加载这些实例。

public class BaseXmlLoader<TBase> where TBase : Base
{
    public List<TBase> LoadFromXml(string filePath)
    {
        var serializer = new XmlSerializer(typeof(TBase));
        // Load your file and deserialize.
    }
}

好处不是很大,因为它不会为你节省那么多代码。但是如果LoadFromXml方法除了类型之外基本相同,那么你就会从中得到一些东西。

答案 2 :(得分:0)

我改变了解决问题的方法并使用Factory模式解决了问题。我还为每个类提供了一个实例方法SetPropertiesFromXml来处理自定义属性。与之前使用的方法不同,这样的方法作为实例方法有意义。

<强>工厂:

public static class BaseFactory 
{
    public static Base GetBase(string id) 
    { 
        switch(id) { case '1': return new Base1(); ... }
    }

    public static T GetBaseList<T>(string xml, string tagName) where T: Base
    {
        List<T> list = new List<T>();
        var nodes = XDocument.Load(xml).Descendants(tagName);
        foreach(XElement node in nodes)
        {
            var base = GetBase(node.Attribute("id").Value);
            base.SetPropertiesFromXml(node);
            list.Add(base as T);
        }
    }
}

<强>碱

public abstract class Base
{
    public virtual void SetPropertiesFromXml(XElement node) 
    { 
        //<Set Properties like: this.Property = node.Element("key");>
    }
}

public class Base1
{
    public override void SetPropertiesFromXml(XElement node)
    {
        //<Set Custom Properties for Base1>

        //Call Base to add the normal properties as well
        base.SetPropertiesFromXml(node);
    }
}

拨打

List<Base1> list = BaseFactory.GetBaseList<Base1>("test.xml", "Base1");