2 using System.Collections.Generic;
5 using System.Xml.Serialization;
18 public string Name {
get;
set; }
38 internal static BindingFlags
AllOfInstance = BindingFlags.FlattenHierarchy | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
42 if ( type == typeof(
string ) )
45 IFormatProvider provider = NumberFormatInfo.InvariantInfo;
49 object[] args =
new object[] { provider };
50 return (
string)type.InvokeMember(
"ToString", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance,
null, obj, args );
52 catch ( MissingMethodException )
54 object[] args =
new object[] { };
55 return (
string)type.InvokeMember(
"ToString", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance,
null, obj, args );
61 if ( type == typeof(
string ) )
64 if ( type == typeof(Type) )
71 object[] args =
new object[] { str, NumberFormatInfo.InvariantInfo };
72 return type.InvokeMember(
"Parse", BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.Public,
null,
null, args );
74 catch ( MissingMethodException )
76 object[] args =
new object[] { str };
77 return type.InvokeMember(
"Parse", BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.Public,
null,
null, args );
81 internal object LoadData( XmlReader reader, Type type,
object obj )
83 Dictionary<string, string> metadata =
null;
84 int depth = reader.Depth;
86 while ( reader.Read() )
88 if ( ( reader.NodeType == XmlNodeType.EndElement ) && ( reader.Depth <= depth ) )
91 if ( reader.NodeType != XmlNodeType.Element )
94 if ( reader.Name ==
"Meta" )
96 if ( metadata ==
null ) metadata =
new Dictionary<string, string>();
98 reader.MoveToFirstAttribute();
101 metadata.Add( reader.Name, reader.ReadContentAsString() );
102 }
while ( reader.MoveToNextAttribute() );
105 if ( reader.IsEmptyElement )
111 if ( ( type != typeof( Type ) ) && ( obj ==
null || ( dObj !=
null && dObj.
IsDestroyed ) ) )
114 string stag = tag as string;
117 throw new NullReferenceException(
"Object of type " + type.Name +
" must be initialized before it can be loaded since there is no factory method or default constructor for it." );
120 if ( reader.Name ==
"Field" || reader.Name ==
"Property" )
122 string mName = reader.GetAttribute(
"Name" );
125 if ( reader.Name ==
"Property" )
127 PropertyInfo propInfo = type.GetProperty( mName, BindingFlags.GetProperty |
AllOfInstance );
128 if ( propInfo ==
null )
throw new ArgumentException( type.Name +
" does not contain property " + mName );
129 object mValue = propInfo.GetValue( obj,
null );
130 mValue =
LoadData( reader, mType, mValue );
131 propInfo.SetValue( obj, mValue,
null );
135 FieldInfo fieldInfo = type.GetField( mName, BindingFlags.GetField |
AllOfInstance );
136 if ( fieldInfo ==
null )
throw new ArgumentException( type.Name +
" does not contain field " + mName );
137 object mValue = fieldInfo.GetValue( obj );
138 mValue =
LoadData( reader, mType, mValue );
139 fieldInfo.SetValue( obj, mValue );
142 else if ( reader.Name ==
"SerializedObject" )
147 object objValue =
null;
149 using ( MemoryStream dataStream =
new MemoryStream( Encoding.Unicode.GetBytes( reader.Value ) ) )
151 XmlSerializer serializer =
new XmlSerializer( type );
152 objValue = serializer.Deserialize( dataStream );
155 while ( !reader.EOF && reader.NodeType != XmlNodeType.EndElement ) reader.Read();
159 else if ( reader.Name ==
"Value" )
164 obj = Enum.Parse( type, reader.Value,
false );
166 obj =
GenParse( type, reader.Value );
168 while ( !reader.EOF && reader.NodeType != XmlNodeType.EndElement ) reader.Read();
170 else if ( reader.Name ==
"Array" )
175 else if ( reader.Name ==
"List" )
178 int itemCount =
int.Parse( reader.GetAttribute(
"Count" ) );
179 obj =
LoadList( reader, mType, itemCount, obj );
183 if ( metadata !=
null )
185 foreach ( KeyValuePair<string, string> entry
in metadata )
192 private void applyMetadata( Type type,
object obj,
string tag,
string value )
208 return value ==
"1" || value.ToLower() ==
"true";
211 internal void SaveData( XmlWriter writer, Type type,
object obj,
bool saveAllFields )
227 writer.WriteElementString(
"Value", ( obj as Type ).AssemblyQualifiedName );
230 bool hasSaveAttrib = saveAllFields || type.GetCustomAttributes( typeof(
SaveAttribute ),
true ).Length > 0;
231 bool hasSaveAllFields = saveAllFields || type.GetCustomAttributes( typeof(
SaveAllFieldsAttribute ),
true ).Length > 0;
233 if ( type.IsClass && type != typeof(
string ) && !hasSaveAttrib )
236 if ( !hasSaveAttrib || ( type.IsPrimitive && type.IsEnum ) )
238 writer.WriteElementString(
"Value",
GenToString( type, obj ) );
244 foreach ( PropertyInfo prop
in type.GetProperties( BindingFlags.GetProperty |
AllOfInstance ) )
249 object[] attribs = prop.GetCustomAttributes(
true );
250 if ( prop.GetCustomAttributes( typeof(
SaveAttribute ),
true ).Length == 0 )
253 object propValue = prop.GetValue( obj,
null );
255 if ( propValue ==
null )
258 Type st = propValue.GetType();
259 SaveMember( writer,
"Property", st, prop, propValue, saveAllFields );
262 foreach ( FieldInfo field
in type.GetFields( BindingFlags.GetField |
AllOfInstance ) )
267 if ( !hasSaveAllFields && field.GetCustomAttributes( typeof(
SaveAttribute ),
true ).Length == 0 )
270 object fieldValue = field.GetValue( obj );
272 if ( fieldValue ==
null )
275 Type st = fieldValue.GetType();
276 SaveMember( writer,
"Field", st, field, fieldValue, saveAllFields );
282 return ( type == typeof( IntPtr ) || type == typeof( UIntPtr ) );
285 private void SaveMember( XmlWriter writer,
string elementName, Type memberType, MemberInfo member,
object memberValue,
bool saveAllFields )
287 writer.WriteStartElement( elementName );
288 writer.WriteAttributeString(
"Name", member.Name );
291 writer.WriteEndElement();
299 writer.WriteStartElement(
"Meta" );
300 writer.WriteAttributeString(
"AddedToGame",
"1" );
301 writer.WriteEndElement();
306 internal object LoadArray( XmlReader reader, Type containerType,
object obj )
308 Type designatedItemType =
null;
309 Array array = (Array)obj;
312 for (
int readItems = 0;
313 readItems < array.GetLength( 0 ) &&
314 reader.Read() && !( reader.NodeType == XmlNodeType.EndElement && reader.Name ==
"Array" ); )
316 if ( reader.NodeType != XmlNodeType.Element )
318 if ( reader.Name !=
"Item" )
320 string name = reader.GetAttribute(
"Name" );
321 if ( name ==
null ) name =
"(undefined)";
322 throw new XmlException(
"Unexpected subelement in List block: " + reader.Name +
", Name = " + name );
325 index = Int16.Parse( reader.GetAttribute(
"Index" ) );
326 designatedItemType =
TypeHelper.
Parse( reader.GetAttribute(
"Type" ) );
328 object item = array.GetValue( index );
331 Type realItemType = item.GetType();
332 if ( designatedItemType != realItemType )
333 throw new XmlException(
"Array item type mismatch: expected " + designatedItemType.Name +
", got " + realItemType.Name +
" at index " + index.ToString() );
336 item =
LoadData( reader, designatedItemType, item );
337 array.SetValue( item, index );
347 while ( list.Count < itemCount )
352 while ( list.Count > itemCount )
354 list.RemoveAt( list.Count - 1 );
358 internal object LoadList( XmlReader reader, Type containerType,
int itemCount,
object obj )
360 object[] listObjects =
new object[itemCount];
361 IList list = (IList)obj;
363 while ( list.Count > itemCount )
365 int removeIndex = list.Count - 1;
370 list.RemoveAt( removeIndex );
373 for (
int i = 0; i < Math.Min( itemCount, list.Count ); i++ )
374 listObjects[i] = list[i];
375 for (
int i = list.Count; i < itemCount; i++ )
376 listObjects[i] =
null;
378 while ( reader.Read() && !( reader.NodeType == XmlNodeType.EndElement && reader.Name ==
"List" ) )
380 if ( reader.NodeType != XmlNodeType.Element )
382 if ( reader.Name !=
"Item" )
384 string name = reader.GetAttribute(
"Name" );
385 if ( name ==
null ) name =
"(undefined)";
386 throw new XmlException(
"Unexpected subelement in List block: " + reader.Name +
", Name = " + name );
389 string tag = reader.GetAttribute(
"Tag" );
391 int itemindex =
int.Parse( reader.GetAttribute(
"Index" ) );
393 if ( tag !=
null && listObjects[itemindex] ==
null )
396 throw new MissingMethodException( String.Format(
"No factory method for type {0}, tag {1}", itemType.Name, tag) );
399 listObjects[itemindex] =
LoadData( reader, itemType, listObjects[itemindex] );
404 for (
int i = 0; i < listObjects.Length; i++ )
405 list.Add( listObjects[i] );
412 if ( type == typeof(
string ) )
426 catch ( KeyNotFoundException )
431 obj = Activator.CreateInstance( type,
true );
434 catch ( MissingMethodException )
443 internal void SaveArray( XmlWriter writer, Type containerType,
object obj )
445 Array array = (Array)obj;
447 writer.WriteStartElement(
"Array" );
450 for (
int i = 0; i < array.GetLength( 0 ); i++ )
452 object item = array.GetValue( i );
453 Type realItemType = item.GetType();
454 writer.WriteStartElement(
"Item" );
455 writer.WriteAttributeString(
"Index", i.ToString() );
457 if ( item is
Tagged ) writer.WriteAttributeString(
"Tag", ( (
Tagged)item ).Tag.ToString() );
458 SaveData( writer, realItemType, item,
false );
459 writer.WriteEndElement();
462 writer.WriteEndElement();
465 internal void SaveList( XmlWriter writer, Type containerType,
object obj )
467 IList list = (IList)obj;
469 writer.WriteStartElement(
"List" );
471 writer.WriteAttributeString(
"Count", list.Count.ToString() );
473 for (
int i = 0; i < list.Count; i++ )
475 Type realItemType = list[i].GetType();
476 writer.WriteStartElement(
"Item" );
478 writer.WriteAttributeString(
"Index", i.ToString() );
479 if ( list[i] is
Tagged ) writer.WriteAttributeString(
"Tag", ( (
Tagged)list[i] ).Tag.ToString() );
480 SaveData( writer, realItemType, list[i],
false );
481 writer.WriteEndElement();
484 writer.WriteEndElement();