Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/280.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为C#中的可序列化类型创建接口?_C#_Interface - Fatal编程技术网

为C#中的可序列化类型创建接口?

为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

在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 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是的,我故意忽略它,以便学习如何正确地实现与此相对类似的接口。序列化只是一个其他人可以理解的简单示例。但序列化并不典型,因为它处理的是大多数接口都不必处理的对象创建(您在这里面临的问题)。特别是,不能处理,因为您只能在创建对象后通过接口使用对象。接口不是这里唯一的解决方案。顺便说一句,我今天偶然发现了。我想你可能会喜欢:)