gpt4 book ai didi

.net - .NET 中对象的自定义序列化

转载 作者:行者123 更新时间:2023-12-03 16:45:26 24 4
gpt4 key购买 nike

我需要将对象列表序列化为平面文件。调用将类似于:

class MyObject
{
public int x;
public int y;
public string a;
public string b;
}

当我序列化这个对象时,记录应该写在一个 ascii 编码的平面文件中。现在,字段 x 的长度应为 10 个字符(右对齐),字段 y 应为 20 个字符(右对齐),字段 a 应为 40(左对齐),字段 b 应为 100 个字符(左对齐)。
我怎么能做到这样的事情。

序列化对象应如下所示:
        25                   8                                     akjsrj                                                                                          jug

我在想可能是我可以将自定义属性应用到字段中,并且可以在运行时决定如何序列化字段..

最佳答案

这是一个使用普通旧反射和自定义属性的解决方案。它只会序列化/反序列化每个文件的一个项目,但您可以轻松地为每个文件添加多个项目的支持。

// Attribute making it possible
public class FlatFileAttribute : Attribute
{
public int Position { get; set; }
public int Length { get; set; }
public Padding Padding { get; set; }

/// <summary>
/// Initializes a new instance of the <see cref="FlatFileAttribute"/> class.
/// </summary>
/// <param name="position">Each item needs to be ordered so that
/// serialization/deserilization works even if the properties
/// are reordered in the class.</param>
/// <param name="length">Total width in the text file</param>
/// <param name="padding">How to do the padding</param>
public FlatFileAttribute(int position, int length, Padding padding)
{
Position = position;
Length = length;
Padding = padding;
}
}

public enum Padding
{
Left,
Right
}


/// <summary>
/// Serializer making the actual work
/// </summary>
public class Serializer
{
private static IEnumerable<PropertyInfo> GetProperties(Type type)
{
var attributeType = typeof(FlatFileAttribute);

return type
.GetProperties()
.Where(prop => prop.GetCustomAttributes(attributeType, false).Any())
.OrderBy(
prop =>
((FlatFileAttribute)prop.GetCustomAttributes(attributeType, false).First()).
Position);
}
public static void Serialize(object obj, Stream target)
{
var properties = GetProperties(obj.GetType());

using (var writer = new StreamWriter(target))
{
var attributeType = typeof(FlatFileAttribute);
foreach (var propertyInfo in properties)
{
var value = propertyInfo.GetValue(obj, null).ToString();
var attr = (FlatFileAttribute)propertyInfo.GetCustomAttributes(attributeType, false).First();
value = attr.Padding == Padding.Left ? value.PadLeft(attr.Length) : value.PadRight(attr.Length);
writer.Write(value);
}
writer.WriteLine();
}
}

public static T Deserialize<T>(Stream source) where T : class, new()
{
var properties = GetProperties(typeof(T));
var obj = new T();
using (var reader = new StreamReader(source))
{
var attributeType = typeof(FlatFileAttribute);
foreach (var propertyInfo in properties)
{
var attr = (FlatFileAttribute)propertyInfo.GetCustomAttributes(attributeType, false).First();
var buffer = new char[attr.Length];
reader.Read(buffer, 0, buffer.Length);
var value = new string(buffer).Trim();

if (propertyInfo.PropertyType != typeof(string))
propertyInfo.SetValue(obj, Convert.ChangeType(value, propertyInfo.PropertyType), null);
else
propertyInfo.SetValue(obj, value.Trim(), null);
}
}
return obj;
}

}

还有一个小演示:
// Sample class using the attributes
public class MyObject
{
// First field in the file, total width of 5 chars, pad left
[FlatFile(1, 5, Padding.Left)]
public int Age { get; set; }

// Second field in the file, total width of 40 chars, pad right
[FlatFile(2, 40, Padding.Right)]
public string Name { get; set; }
}

private static void Main(string[] args)
{
// Serialize an object
using (var stream = File.OpenWrite("C:\\temp.dat"))
{
var obj = new MyObject { Age = 10, Name = "Sven" };
Serializer.Serialize(obj, stream);
}

// Deserialzie it from the file
MyObject readFromFile = null;
using (var stream = File.OpenRead("C:\\temp.dat"))
{
readFromFile = Serializer.Deserialize<MyObject>(stream);
}

}

关于.net - .NET 中对象的自定义序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6293884/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com