基於問題的細化,我推斷你對不同的輸入有多種不同的格式。這是IFormatter的一個實現,它應該可以幫助您實現這一目標。請注意,這是在幾個不同的方式,哈克打破,並附帶任何排序保證:
void Test()
{
var serializer = new FixedWidthSerializer<MyClass>();
var ms = new MemoryStream();
serializer.Serialize(ms, new MyClass { Age = 30, FirstName = "John", LastName = "Doe"});
ms.Position = 0;
var newMyClass = (MyClass)serializer.Deserialize(ms);
}
[Serializable]
private class MyClass
{
public String FirstName { get; set; }
public String LastName;
public Int32 Age { get; set; }
}
public class FixedWidthSerializer<T> : IFormatter
{
private readonly FixedWidthFieldDefinition[] _fieldDefinition;
public FixedWidthSerializer()
:
this(FormatterServices.GetSerializableMembers(typeof(T)).Select(sm=>new FixedWidthFieldDefinition(sm.Name, 100)).ToArray())
{ }
public FixedWidthSerializer(FixedWidthFieldDefinition[] fieldDefinition)
{
if (fieldDefinition == null) throw new ArgumentNullException("fieldDefinition");
_fieldDefinition = fieldDefinition;
Context = new StreamingContext(StreamingContextStates.All);
}
public class FixedWidthFieldDefinition
{
public String FieldName { get; protected set; }
public Int32 CharLength { get; protected set; }
public FixedWidthFieldDefinition(String fieldName, Int32 charLength)
{
FieldName = fieldName;
CharLength = charLength;
}
}
public object Deserialize(Stream serializationStream)
{
var streamReader = new StreamReader(serializationStream);
var textLine = streamReader.ReadLine();
if (textLine == null)
throw new SerializationException("Ran out of text!");
var obj = FormatterServices.GetUninitializedObject(typeof (T));
var memberDictionary = FormatterServices.GetSerializableMembers(obj.GetType(), Context).ToDictionary(mi => mi.Name);
var offset = 0;
foreach (var fieldDef in _fieldDefinition)
{
if (offset + fieldDef.CharLength > textLine.Length)
throw new SerializationException("Line was too short!");
// Read the current field and increase the offset
var fieldStringValue = textLine.Substring(offset, fieldDef.CharLength);
offset += fieldDef.CharLength;
MemberInfo memberInfo;
if (!memberDictionary.TryGetValue(fieldDef.FieldName, out memberInfo))
throw new SerializationException("You asked for the member '" + fieldDef.FieldName + "', but it doesn't exist on type '" + typeof (T) + "'");
var memberAsField = memberInfo as FieldInfo;
if (memberAsField != null)
memberAsField.SetValue(obj, Convert.ChangeType(fieldStringValue.TrimEnd(), memberAsField.FieldType));
else
throw new SerializationException("I don't know what to make of the property '" + fieldDef.FieldName + "'");
}
return obj;
}
public void Serialize(Stream serializationStream, object graph)
{
var serializableMembers = FormatterServices.GetSerializableMembers(graph.GetType());
var membersToSerialize = _fieldDefinition.Select(fd => serializableMembers.First(sm => sm.Name == fd.FieldName)).ToArray();
var objectData = FormatterServices.GetObjectData(graph, membersToSerialize);
var sb = new StringBuilder(_fieldDefinition.Sum(fd => fd.CharLength));
for (var i = 0; i < _fieldDefinition.Length; i++)
sb.Append(((String) Convert.ChangeType(objectData[i], typeof (String))).PadRight(_fieldDefinition[i].CharLength), 0, _fieldDefinition[i].CharLength);
var sw = new StreamWriter(serializationStream);
sw.WriteLine(sb.ToString());
sw.Flush();
}
public ISurrogateSelector SurrogateSelector { get; set; }
public SerializationBinder Binder { get; set; }
public StreamingContext Context { get; set; }
}
在你的榜樣,前8個字符的用戶名,在接下來的8個字符是城市,而未來5個字符郵政編碼...(不,這不僅僅是空間標準化。)這是實際的格式嗎? – Ryan
定義'更好'。比什麼好?你有什麼嘗試?你所嘗試的什麼都不起作用? –
@Chris,我用我目前的方法更新了這個問題 – testuser