为C#中的可序列化类型创建接口?
在Haskell中,我们可以这样做:为C#中的可序列化类型创建接口?,c#,interface,C#,Interface,在Haskell中,我们可以这样做: class Binary a where encode :: a -> ByteString decode :: ByteString -> a instance Binary Int where encode x = ... decode bytes = ... public interface IBinary<T> { byte[] Encode(); // Alterantive de
class Binary a where
encode :: a -> ByteString
decode :: ByteString -> a
instance Binary Int where
encode x = ...
decode bytes = ...
public interface IBinary<T>
{
byte[] Encode(); // Alterantive definition as extension method below
}
public static class Binary
{
public static T Decode<T>(byte[] bytes) where T : IBinary<T>¨
{
// deserialization logic here
}
// If you want, you can define Encode() as an extension method instead:
public static byte[] Encode<T, TBinary>(this TBinary binary)
where TBinary : IBinary<T>
{
// serialization logic here
}
}
这定义了一个接口Binary
,该接口Int
实现。我们现在可以将Int
s转换为字节数组,反之亦然。我希望在C#中实现同样的功能,我的第一反应是创建接口:
interface Binary<T> {
byte[] Encode(T);
static T Decode(byte[]);
}
接口二进制文件{
字节[]编码(T);
静态T解码(字节[]);
}
但是这失败了,因为解码
不允许是静态的
我如何在C#中尽可能干净地实现这一点
请注意,我不希望出现这样的解决方案,即创建一个“空”或部分初始化的t
,然后通过调用非静态解码来填充它:这将是一个混乱的过程,并留下一个窗口,在该窗口中,对象的使用是潜在的错误源
谢谢 没有直接将静态方法添加到接口中的真正方法,但是可以做的是将此方法添加到扩展类中,或者在派生类中实现它(这几乎是静态方法所能做的):
但在这种情况下(如果出于某种原因我选择不使用标准.Net序列化框架),我可能会创建自己的序列化程序类:
interface ISerializer<T> : IDisposable
{
virtual byte[] Serialize(T instance);
virtual T DeSerialize(byte[] stream);
}
Class MySerializer<T> : ISerializer<T>
{
public override byte[] Serialize(object instance)
{
// .. serialization logic
}
public override T DeSerialize(byte[] stream)
{
// .. deserialization logic
}
public void Dispose()
{
// .. dispose all managed resources here
}
}
class MyClass
{
}
接口ISerializer:IDisposable
{
虚拟字节[]序列化(T实例);
虚拟T反序列化(字节[]流);
}
类MySerializer:ISerializer
{
公共重写字节[]序列化(对象实例)
{
//..序列化逻辑
}
公共重写T反序列化(字节[]流)
{
//…反序列化逻辑
}
公共空间处置()
{
//…在此处处置所有托管资源
}
}
类MyClass
{
}
用法:
MyClass instance = new MyClass();
MyClass newInstance = null;
using(ISerializer<MyClass> serializer = new MySerializer<MyClass>())
{
bytes[] bytes = serializer.Serialize(instance);
newInstance = serializer.DeSerialize(bytes);
}
MyClass实例=新建MyClass();
MyClass newInstance=null;
使用(ISerializer serializer=new MySerializer())
{
bytes[]bytes=serializer.Serialize(实例);
newInstance=serializer.DeSerialize(字节);
}
我通常会将这样的代码分成两种类型:一种是基类或接口(取决于我的需要),通常是泛型的,表示实际数据;另一种是带有静态和扩展方法的静态助手类。在本例中,我可能会这样做:
class Binary a where
encode :: a -> ByteString
decode :: ByteString -> a
instance Binary Int where
encode x = ...
decode bytes = ...
public interface IBinary<T>
{
byte[] Encode(); // Alterantive definition as extension method below
}
public static class Binary
{
public static T Decode<T>(byte[] bytes) where T : IBinary<T>¨
{
// deserialization logic here
}
// If you want, you can define Encode() as an extension method instead:
public static byte[] Encode<T, TBinary>(this TBinary binary)
where TBinary : IBinary<T>
{
// serialization logic here
}
}
公共接口IBinary
{
byte[]Encode();//以下扩展方法的替代定义
}
公共静态类二进制
{
公共静态T解码(字节[]字节),其中T:IBinary¨
{
//这里的反序列化逻辑
}
//如果需要,可以将Encode()定义为扩展方法:
公共静态字节[]编码(此二进制)
地点:伊比利亚
{
//这里的序列化逻辑
}
}
现在,您将通过创建这样的类来使用此层次结构
public class BinaryEncodableInteger : IBinary<int>
{
// must have this if defined in interface,
// but if defined as extension method you get it for free
public byte[] Encode()
{
// serialization logic here
}
}
公共类二进制EncodableInteger:IBinary
{
//如果在接口中定义,则必须具有此功能,
//但如果定义为扩展方法,您可以免费获得它
公共字节[]编码()
{
//这里的序列化逻辑
}
}
并将该类用作
var binInt = new BinaryEncodableInteger();
var bytes = binInt.Encode();
var decoded = Binary.Decode<BinaryEncodableInteger>(bytes);
var binInt=new BinaryEncodableInteger();
var bytes=binInt.Encode();
var decoded=二进制.Decode(字节);
我认为C#和Haskell之间的接口
s差异太大,无法解决这两种情况下的问题。我宁愿使用。尽管他们没有提供这个问题的通用解决方案,但据我所知,因为他们也通过静态方法工作
我定义了一个简单的二进制
类,它包含一个字节数组
,以及从int
到int的转换运算符
class Binary
{
public Binary(byte[] value)
{
this.Value = value.ToArray();
}
public byte[] Value { get; private set; }
// User-defined conversion from Binary to int
public static implicit operator int(Binary b)
{
return b.Value[0] + (b.Value[1] << 8) + (b.Value[2] << 16) + (b.Value[3] << 24);
}
// User-defined conversion from int to Binary
public static implicit operator Binary(int i)
{
var result = new byte[4];
result[0] = (byte)(i & 0xFF);
result[1] = (byte)(i >> 8 & 0xFF);
result[2] = (byte)(i >> 16 & 0xFF);
result[3] = (byte)(i >> 24 & 0xFF);
return new Binary(result);
}
}
您可以去实现自己的特定逻辑,但这应该说明原理。在.NET Framework中构建了大量的序列化基础结构-您是否意识到了这一点,并故意忽略了它?如果是,为什么?@Damien_The_unsiver是的,我故意忽略它,以便学习如何正确地实现与此相对类似的接口。序列化只是一个其他人可以理解的简单示例。但序列化并不典型,因为它处理的是大多数接口都不必处理的对象创建(您在这里面临的问题)。特别是,不能处理,因为您只能在创建对象后通过接口使用对象。接口不是这里唯一的解决方案。顺便说一句,我今天偶然发现了。我想你可能会喜欢:)