首页 / C# / C#-接口和对象反序列化
C#-接口和对象反序列化
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了C#-接口和对象反序列化,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含7094字,纯文字阅读大概需要11分钟。
内容图文
我有一个定义一个可序列化为字节数组的类的接口.
public interface IByteSerializable
{
byte[] GetBytes();
}
一个自然的伙伴是反序列化方法,我想返回一个实现IByteSerializable的对象.
我正在努力设计这种界面.
这似乎没有道理:
public interface IByteSerializable
{
byte[] GetBytes();
IByteSerializable GetObject(byte[] bytes);
}
因为GetObject()的实现不能是静态的,并且使用虚拟IByteSerializable对象只是为了调用GetObject()方法来反序列化我所追求的实际对象也没有意义.
这样做似乎也没有任何意义:
public interface IByteSerializableFactory
{
IByteSerializable GetObject(byte[] bytes);
}
Factory类可以解决该问题,但是感觉会导致类爆炸.同样,给定的IByteSerializable子类如何序列化然后反序列化的细节是相互依赖的,因此将它们保留在同一位置而不是两个不同的类中是有意义的.显然,反序列化给定IByteSerializable对象所需的确切过程完全取决于该对象的GetBytes()方法的编写方式.
我可以使用通用的设计或图案来解决此问题吗?
解决方法:
关于您的问题,关于接口,类和模式有很多不同的意见.我个人的喜好是使用一个byte []属性实现一个接口,并使用一个虚方法实现一个抽象类(甚至完全失去该接口,这可能不是您的选择,并且不能与DI和单元测试一起很好地使用):
public interface IByteSerializable
{
byte[] SerializableByteObject { get; }
}
public abstract class ByteSerializable : IByteSerializable
{
public byte[] SerializableByteObject { get; }
protected virtual byte[] GetBytes() {
return SerializableByteObject;
}
public abstract IByteSerializable GetObject();
//{ // You can make this method virtual and use Impl method:
// GetObjectImpl(SerializableByteObject);
//}
protected internal IByteSerializable GetObjectImpl(byte[] bytes) {
// If you need a default implementation (GetObject() should be protected virtual then)
// return IByteSerializable...;
}
}
我想强调的是,接口VS抽象类是一个无休止的讨论.如果您可以在不实现接口的情况下进行操作,而仅使用抽象类-我强烈建议您这样做.
更新3/18/17:回复评论(定义行为是界面的目的)并解释我如何看待它,并在下面添加解释.
在这种情况下,我们定义的“行为”是“一个对象应该可以转换为字节数组.转换结果应该可以转换回相同的对象.”因此,我们实际上是在定义对象和字节数组的行为(因为对象反序列化后-它不再是同一对象,而只是字节数组).
在我看来,这是纯工厂模式方案.
// Let's define an interface for our serializable type of objects factory
public interface IByteSerializableFactory<T>
{
T CreateFromBytes(byte[] objectDataToUse);
byte[] CovertToBytes(T objectToConvert);
}
// Interface for any class that needs a serialization factory
// This is not even necessary, but I like it to enforce people to implement simple methods that reference the factory.
public interface IByteSerializable<T>
{
IByteSerializableFactory<T> GetFactory();
}
// Now a moment comes for us to have this kind of class. We need to build a factory first (because our interface requires a GetFactory() implementation. We can lose the IByteSerializable interface altogether, but then we lose a way to let people know which factory should be used.
public class SomeBaseClassSerializationFactory : IByteSerializableFactory<SomeBaseClass>
{
public SomeBaseClass CreateFromBytes(byte[] objectDataToUse) { //...
return new SomeClass();
}
public byte[] CovertToBytes(SomeBaseClass objectToConvert) { //...
return new byte[1];
}
}
// We have a factory, let's implement a class.
public abstract class SomeBaseClass : IByteSerializable<SomeBaseClass>
{
public virtual IByteSerializableFactory<SomeBaseClass> GetFactory() {
return new SomeBaseClassSerializationFactory();
}
}
public class SomeClass : SomeBaseClass {
// Now we're independent. Our derived classes do not need to implement anything.
// If the way the derived class is serialized is different - we simply override the method
}
更新2 3/18/17:在不同答案下回复评论(通过简单使用接口的通用实现).
不幸的是,没有干净的方法可以做到这一点.通过使用一些作弊,定义定义序列化方法的类以及使用反射来返回正确的类型,这是一种肮脏的方式(我个人认为:“ BAD BAD BAD!”).下面的示例将在序列化方法中使用大量自定义逻辑,以使用不同类型的正确字段:
// You define an enum with action and a dictionary with a collection of serialization methods.
public enum SerializationAction {
ToBytes,
ToObject
}
// It can also be an enum, but it's easier to test with a collection of strings.
public static readonly string[] SerializationKindList = new string[] {
"FirstKind",
"SecondKind"
};
// This generic class can have an implementation of all the handlers. Additional switching can be done by type, or reflection can be used to find properties for different classes and construct different classes.
public class SerializationMethod {
public object ProcessByKind (string kindToUse, SerializationAction action, object objectToProcess) {
if (kindToUse == "FirstKind") {
if (action == SerializationAction.ToBytes) {
return new byte[1];
}
return new SomeClass(); // These would need to be your hard implementations. Not clean.
} else {
throw new NotImplementedException();
}
}
}
// This struct type defines the serialization method and is required for the interface implementation
public struct ByteSerialization
{
public string SerializationTypeName { get; private set; }
public ByteSerialization(string kindToUse) {
if (!SerializationKindList.Contains(kindToUse)) {
throw new ArgumentException();
}
SerializationTypeName = kindToUse;
}
public byte[] Deserialize(object objectToProcess) {
var serializationMethod = new SerializationMethod();
return (byte[])serializationMethod.ProcessByKind(this.SerializationTypeName, SerializationAction.ToBytes, objectToProcess);
}
public object Serialize(byte[] byteArrayToProcess) {
var serializationMethod = new SerializationMethod();
return serializationMethod.ProcessByKind(this.SerializationTypeName, SerializationAction.ToObject, byteArrayToProcess);
}
}
// Interface for any class that needs to use generic serialization
public interface IByteSerializable
{
ByteSerialization serializationType { get; }
}
// Creating extension methods for the interface to make the life easier
public static class IByteSerializableExtensions {
public static byte[] DeserializeObjectIntoBytes(this IByteSerializable objectToProcess) {
return objectToProcess.serializationType.Deserialize(objectToProcess);
}
public static void SerializeObjectFromBytes(this IByteSerializable objectToProcess, byte[] fromBytes) {
var someObjectData = objectToProcess.serializationType.Serialize(fromBytes);
}
}
// Abstract base class implementation with static readonly field.
// Only downside - there is no way to enforce the config of this field in the constructor from the interface.
// There also no way to make sure this field always gets set for other implementations of IByteSerializable
public abstract class SomeBaseClass : IByteSerializable
{
private static readonly ByteSerialization _serializationType = new ByteSerialization("FirstKind");
public ByteSerialization serializationType { get { return _serializationType; } }
}
public class SomeClass : SomeBaseClass {
}
// And here's how one would use it. You will need to create a new object of the class before serializing from bytes.
var someClass = new SomeClass();
var bytes = someClass.DeserializeObjectIntoBytes();
var someClass2 = new SomeClass();
var byteArray = new byte[1];
someClass2.SerializeObjectFromBytes(byteArray);
内容总结
以上是互联网集市为您收集整理的C#-接口和对象反序列化全部内容,希望文章能够帮你解决C#-接口和对象反序列化所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。