我正在为Apache编写一个GenericDeserializer。我的类从IDeserializer<T>包实现了Confluent.Kafka.Net。我需要提供一个具有此签名的反序列化方法,T Deserialize(ReadOnlySpan<byte> data, bool isNull, SerializationContext context)。但我也需要使用汇流的Deserializers类,因为它实现了一些低层次的细节,例如将网络中的大endian消息解码为原语类型、字节数组、UTF8字符串等。简化的一个例子可能是删除我为使编译器高兴而引入的强制转换的使用。
我在这个方法中的逻辑是这样的,在已经实现的Deserializers类中使用每个受支持的类型。对于没有在该类的帮助下反序列化的其他类型,请使用Json序列化。这是我的代码:
public class GenericDeserializer<T> : IDeserializer<T>
{
public T Deserialize(ReadOnlySpan<byte> data, bool isNull, SerializationContext context)
{
var type = typeof(T);
if (type == typeof(double))
{
var retVal = Deserializers.Double.Deserialize(data, isNull, context);
return (T) (object) retVal;
}
if (type == typeof(float))
{
var retVal = Deserializers.Single.Deserialize(data, isNull, context);
return (T) (object) retVal;
}
if (type == typeof(int))
{
var retVal = Deserializers.Int32.Deserialize(data, isNull, context);
return (T) (object) retVal;
}
if (type == typeof(long))
{
var retVal = Deserializers.Int64.Deserialize(data, isNull, context);
return (T) (object) retVal;
}
if (type == typeof(Null))
{
var retVal = Deserializers.Null.Deserialize(data, isNull, context);
return (T) (object) retVal;
}
if (type == typeof(string))
{
var retVal = Deserializers.Utf8.Deserialize(data, isNull, context);
return (T) (object) retVal;
}
if (type == typeof(byte[]))
{
var retVal = Deserializers.ByteArray.Deserialize(data, isNull, context);
return (T) (object) retVal;
}
if (isNull)
{
return default;
}
return JsonSerializer.Deserialize<T>(data, new JsonSerializerOptions()
{
PropertyNameCaseInsensitive = true
});
}
}以下是Deserializers类的Confluent.Kafka https://github.com/confluentinc/confluent-kafka-dotnet/blob/master/src/Confluent.Kafka/Deserializers.cs的来源
发布于 2020-10-16 14:46:37
您可以定义Types和Deserializers之间的映射。例如,您可以这样做:
public class GenericDeserializer<T> : IDeserializer<T>
{
private readonly ImmutableDictionary<Type, object> _deserializers =
new Dictionary<Type, object>
{
{ typeof(double), Deserializers.Double },
{ typeof(float), Deserializers.Single },
{ typeof(int), Deserializers.Int32 },
{ typeof(long), Deserializers.Int64 },
{ typeof(Null), Deserializers.Null },
{ typeof(string), Deserializers.Utf8 },
{ typeof(byte[]), Deserializers.ByteArray },
}.ToImmutableDictionary();
}您不能在字典的值类型参数中使用IDeserializer<T>,这就是为什么它是一个object。
然后,您所需要做的就是进行查找调用,并尝试将值转换为IDeserializer<T>。
if (_deserializers.ContainsKey(typeof(T)))
{
var deserializer = _deserializers[typeof(T)] as IDeserializer<T>;
...
}如果找到了该类型,则可以根据isNull值进行分支:
if (_deserializers.ContainsKey(typeof(T)))
{
var deserializer = _deserializers[typeof(T)] as IDeserializer<T>;
var retVal = deserializer.Deserialize(data, isNull, context);
return !isNull ? retVal : default;
}如果找不到它,那么可以使用JsonSerializer作为后盾。
return JsonSerializer.Deserialize<T>(data, new JsonSerializerOptions()
{
PropertyNameCaseInsensitive = true
});最后的代码如下所示:
public class GenericDeserializer<T> : IDeserializer<T>
{
private readonly ImmutableDictionary<Type, object> _deserializers =
new Dictionary<Type, object>
{
{ typeof(double), Deserializers.Double },
{ typeof(float), Deserializers.Single },
{ typeof(int), Deserializers.Int32 },
{ typeof(long), Deserializers.Int64 },
{ typeof(Null), Deserializers.Null },
{ typeof(string), Deserializers.Utf8 },
{ typeof(byte[]), Deserializers.ByteArray },
}.ToImmutableDictionary();
public T Deserialize(ReadOnlySpan<byte> data, bool isNull, SerializationContext context)
{
if (_deserializers.ContainsKey(typeof(T)))
{
var deserializer = _deserializers[typeof(T)] as IDeserializer<T>;
var retVal = deserializer.Deserialize(data, isNull, context);
return !isNull ? retVal : default;
}
return JsonSerializer.Deserialize<T>(data, new JsonSerializerOptions()
{
PropertyNameCaseInsensitive = true
});
}
}发布于 2020-10-16 05:18:22
您可以摆脱Deserialize方法中的分支,而是将该逻辑移到只执行一次的位置--构造位置。对于任何输入,GenericDeserializer<T>的一个实例总是执行相同的分支,因为该实例已经绑定到特定的输出类型T中,例如int,并且在使用它们的实现时加倍--只返回它们的实现,其余的使用您的实现。
class JsonDeserializer<T> : IDeserializer<T>
{
public T Deserialize(ReadOnlySpan<byte> data, bool isNull, SerializationContext context)
{
if (isNull)
{
return default;
}
return JsonSerializer.Deserialize<T>(data, new JsonSerializerOptions()
{
PropertyNameCaseInsensitive = true
});
}
}
IDeserializer<T> CreateDeserializer<T>()
{
var type = typeof(T);
if (type == typeof(double))
{
return (IDeserializer<T>) Deserializers.Double;
}
if (type === typeof(long))
{
return (IDeserializer<T>) Deserializers.Int64;
}
// ...
return new JsonDeserializer<T>();
}https://codereview.stackexchange.com/questions/250719
复制相似问题