2016-05-23 134 views
0

我有多個類,如:靜態方法調用

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; 
    } 
} 

所以基類也有一些獨特的性能。這就是爲什麼我首先需要繼承的原因。

+0

不可能的。靜態方法綁定到它們的定義類。 –

+0

如果你想要多態性,你爲什麼不把它變成實例方法?或者可以返回不同類型的列表的單個泛型靜態方法? –

+0

你打算如何調用'PrepareBase'?你想用它輸出什麼? (換句話說......假設你可以這麼做 - 就像你寫的那樣,使用它的語句看起來像什麼?) – Amit

回答

0

我改變了我的方法解決問題,並使用工廠模式解決它。我還爲每個類提供了一個實例方法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"); 
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方法除了類型之外基本相同,那麼您就會從中獲得某些東西。

+0

他們不是完全相同的。 'Base1'和'Base2'具有一個或兩個自定義屬性,這些屬性也在'LoadFromXml'方法中加載。這就是爲什麼我首先嚐試繼承方式的原因。 –

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"); 
    } 
} 
+0

我意識到我遺漏了一個重要的細節,所以我在不同的基類中爲自己的問題添加了更多關於自定義屬性的信息。 –

+0

答覆已更新。 –