c#中的通用部分应用函数

时间:2013-12-11 12:55:31

标签: c# generics serialization functional-programming

某些类组中有二进制序列化方法。算法很简单:以某种顺序递归写入所有嵌套对象中的所有基本类型字段。虽然类的结构可能不同,但我需要一些功能来跟踪写入的数据。所以我最终想到在一些xml中存储二进制流中的字段名称和偏移量。 这里是序列化的示例接口方法实现,必须在该组中的所有类中实现:

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 个答案:

答案 0 :(得分: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);
}