2013-12-11 22 views
1

某些類組中存在二進制序列化方法。該算法很簡單:遞歸地按照某種順序在所有嵌套對象中寫入所有基元類型字段。雖然類的結構可能會有所不同,但我需要一些用於跟蹤數據寫入的功能。所以我最終想到在二進制流中存儲字段名稱和偏移量在xml。 這裏的示例界面的方法實現爲串行化,必須在所有的類,該組內被實施:c中的泛型部分應用函數#

public XElement mySerialize(BinaryWriter bw) 
{ 
    var x = new XElement("Class0", 
     serializeAndProduceLog(id, "id", bw, bw.Write), 
     serializeAndProduceLog(classFieldString, "classFieldString", bw, bw.Write), 
     serializeAndProduceLog(classFieldLong, "classFieldLong", bw, bw.Write), 
     classFieldObject0.mySerialize(bw), 
     classFieldList.Select(o => o.mySerialize) 
    ); 
    return x; 
} 

以下是實用方法:

private XElement serializeAndProduceLog<T>(T field, string name, BinaryWriter bw, Action<T> f) 
    { 
     return new XElement(name, new XAttribute("type", field.GetType()), new Attribute("offset", writeField(field, bw, f))); 
    } 

    private long writeField<T>(T v, BinaryWriter bw, Action<T> f) 
    { 
     var p = bw.BaseStream.Position; 
     f(v); 
     return bw.BaseStream.Position - p; 
    } 

writeField方法執行二進制寫入操作和返回的量字節已寫入。 我不想爲每個BinaryWriter.Write重載的實例編寫一堆重載的包裝,所以泛型參數f會訣竅。 現在,由於BinaryWriterBinaryWriter.Write總是相同的,我的興致是擺脫枯燥的重複參數傳遞。我想引入部分應用功能,如

Func<int, string, XElement> serializeAndProduceLogInt = (field, name) => serializeAndProduceLog(field, name, bw, bw.Write); 

但是使用泛型參數而不是「int」。這在C#中可能嗎?

回答

1
Func<T, string, XElement> SerializeAndProduceLogger<T>(BinaryWriter bw) 
{ 
    var method = typeof(BinaryWriter).GetMethod("Write", new Type[] { typeof(T) }); 
    if(method == null) throw new ArgumentException("No overload of write for type"); 

    Action<T> act = f => { method.Invoke(bw, new object[] { f }) }; 
    return (T field, string name) => serializeAndProduceLog(field, name, bw, act); 
} 
+0

此代碼看起來非常複雜,反射。我想找到在編譯時推斷類型的方法。但無論如何,謝謝。 –

+0

@SergeyPrytkov - 我相當肯定你不能不使用反射做到這一點。泛型不適用於重載,因爲無法在方法調用站點對泛型參數進行專門化。 – Lee