2016-06-20 14 views
0

在規定的抽象類,我想創造出可以傳遞給定義爲這樣的方法兩個靜態方法:如何傳遞一個具有通用約束的方法作爲Func <T>?

public static void AddType<T>(
    Func<XmlReader, T> ReaderFunc, 
    Func<T, XmlWriter> WriterFunc){ 
    /*Magic stuff happens here*/ 
} 

這將是靜態類:

public abstract class XmlModel : IXmlSerializable{ 

    static XmlModel(){ 
     //Type Inference kicks in with other tests, but not this one T_T 
     MyStaticClass.AddType(ReadModel, WriteModel); 
    } 

    private static T ReadModel<T>(XmlReader Reader) where T : XmlModel, new(){ 
     T Model = new T(); 
     T.ReadXml(Reader); 
     return T; 
    } 

    private static void WriteModel<T>(T Model, XmlWriter Writer) where T : XmlModel{ 
     T.WriteXml(Writer); 
    } 

    public abstract void ReadXml(XmlReader Reader); 
    public abstract void WriteXml(XmlWriter Writer); 
} 

我想原因能夠通過ReadModelWriteModelAddType方法是因爲該方法屬於一個包含以下擴展方法的類,它最終會使我非常容易地從Xml中讀取和寫入值:

public static class ReaderWriters{ 
    private static Dictionary<Type, object> 
     _dctTypeReader = new Dictionary<Type, object>(); 
    private static Dictionary<Type, object> 
     _dctTypeWriter = new Dictionary<Type, object>(); 

    /// <summary> 
    /// Add type reader/writer pair. 
    /// </summary> 
    /// <typeparam name="T">Type of object to be read and written.</typeparam> 
    /// <param name="ReaderFunc">Func which returns value read.</param> 
    /// <param name="WriterFunc">Func which writes value.</param> 
    public static void AddType<T>(
     Func<XmlReader, T> ReaderFunc, 
     Func<T, XmlWriter> WriterFunc) { 
     _dctTypeReader.Add(typeof(T), ReaderFunc); 
     _dctTypeWriter.Add(typeof(T), WriterFunc); 
    } 

    public static T Read<T>(this XmlReader Reader){ 
     if (_dctTypeReader.ContainsKey((Key = typeof(T))) || (Key = 
      _dctTypeReader.Keys.FirstOrDefault(K => typeof(T).BaseType == K)) != null) { 
      if (Reader.ReadToFollowing(typeof(T).Name)) 
       return (_dctTypeReader[ Key ] as Func<XmlReader, T>)(Reader); 
      else 
       throw new XmlException(string.Format("Failed to read into type {0}. Value was not found at expected location.", typeof(T).Name)); 
     } else 
      throw new KeyNotFoundException(
       string.Format("Please define a method for reading objects of type {0}", typeof(T).Name)); 
    } 

    public static void Write<T>(this T toWrite, XmlWriter Writer){ 
     /*Magic happens here*/ 
    } 
} 

這樣我就可以繼承XmlModel:

public class Foo : XmlModel{ 
    public override void ReadXml(XmlReader Reader){ 
     /*Magic Happens Here*/ 
    } 
    public override void WriteXml(XmlWriter Writer){ 
     /*Magic Happens Here*/ 
    } 
} 

,並能夠說Foo Model = SomeXmlReader.Read<Foo>()Model.Write(SomeXmlWriter) ...

就是我想在這裏完成可能嗎?我的意思是,我幾乎要求自己必須手動完成這些工作,並且每個類都繼承我的類,但是如果有某種方式可以這樣做,我只需要在抽象類中定義它,那麼會讓我如此開心...

回答

2

是的,你要做什麼是可行的。您遇到的大部分困難似乎都來自過度使用靜態。一般來說,除非你有很好的理由,否則不要使用靜態。這個問題是可以解決的,只需讓你的類是非靜態的,並將類的實現放在類的層次上即可。

在下面的示例代碼中,我剛剛從XmlModel中刪除靜態,將通用參數移至類級別,並將幾個變量重命名爲遵循標準命名約定(局部變量和參數的小寫名稱)。除非我誤解,否則這應該或多或少地做你正在尋找的東西。

public static class MyStaticClass 
{ 
// Define other methods and classes here 
    public static void AddType<T>(
     Func<XmlReader, T> ReaderFunc, 
     Action<T, XmlWriter> WriterFunc){ 
     /*Magic stuff happens here*/ 
    } 
} 


public abstract class XmlModel<T> where T : XmlModel<T>, new() 
{ 
    public XmlModel(){ 
     //Type Inference kicks in with other tests, but not this one T_T 
     MyStaticClass.AddType<T>(ReadModel, WriteModel); 
    } 

    private T ReadModel(XmlReader reader) 
    { 
     T model = new T(); 
     model.ReadXml(reader); 
     return model; 
    } 

    private void WriteModel(T model, XmlWriter writer) 
    { 
     model.WriteXml(writer); 
    } 

    public abstract void ReadXml(XmlReader reader); 
    public abstract void WriteXml(XmlWriter writer); 
} 
  • 列表項
+0

那麼我將如何繼承這個抽象類呢? '公共類Foo:XmlModel '?另外,當我聲明一個類繼承時,我得到以下錯誤:'XmlModel .XmlModel()無法訪問,因爲它的保護級別爲' – Will

+0

該解決方案存在一些問題,儘管它很接近。首先是將私有抽象類構造函數聲明爲繼承抽象類的類爆炸(不能訪問私有構造函數)。其次,如果我要聲明繼承我的抽象類的同一類的多個實例,則將爲每個實例調用AddType 。只需要爲每個類調用一次AddType (因此是靜態構造函數)。 – Will

+0

你是正確的構造函數是公開的,但你不能使用靜態構造函數。相反,您必須更新您的AddType方法以跟蹤已添加的類型並跳過重複項。另一個選擇是在XmlModel中有一個線程安全的靜態屬性,以告訴你是否需要調用AddType。讓我知道你是否想要這些解決方案的例子。 –

相關問題