2 using System.Collections.Generic;
6 using System.Xml.Serialization;
10 using System.Globalization;
19 public string Name {
get;
set; }
39 internal static BindingFlags AllOfInstance = BindingFlags.FlattenHierarchy | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
41 string GenToString( Type type,
object obj )
43 if ( type == typeof(
string ) )
46 IFormatProvider provider = NumberFormatInfo.InvariantInfo;
50 object[] args =
new object[] { provider };
51 return (
string)type.InvokeMember(
"ToString", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance, null, obj, args );
53 catch ( MissingMethodException )
55 object[] args =
new object[] { };
56 return (
string)type.InvokeMember(
"ToString", BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance, null, obj, args );
60 object GenParse( Type type,
string str )
62 if ( type == typeof(
string ) )
65 if ( type == typeof(Type) )
72 object[] args =
new object[] { str, NumberFormatInfo.InvariantInfo };
73 return type.InvokeMember(
"Parse", BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.Public, null, null, args );
75 catch ( MissingMethodException )
77 object[] args =
new object[] { str };
78 return type.InvokeMember(
"Parse", BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.Public, null, null, args );
82 internal object LoadData( XmlReader reader, Type type,
object obj )
84 Dictionary<string, string> metadata = null;
85 int depth = reader.Depth;
87 while ( reader.Read() )
89 if ( ( reader.NodeType == XmlNodeType.EndElement ) && ( reader.Depth <= depth ) )
92 if ( reader.NodeType != XmlNodeType.Element )
95 if ( reader.Name ==
"Meta" )
97 if ( metadata == null ) metadata =
new Dictionary<string, string>();
99 reader.MoveToFirstAttribute();
102 metadata.Add( reader.Name, reader.ReadContentAsString() );
103 }
while ( reader.MoveToNextAttribute() );
106 if ( reader.IsEmptyElement )
112 if ( ( type != typeof( Type ) ) && ( obj == null || ( dObj != null && dObj.
IsDestroyed ) ) )
115 string stag = tag as string;
117 if ( !TryCreateObject( type, stag, out obj ) )
118 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." );
121 if ( reader.Name ==
"Field" || reader.Name ==
"Property" )
123 string mName = reader.GetAttribute(
"Name" );
126 if ( reader.Name ==
"Property" )
128 PropertyInfo propInfo = type.GetProperty( mName, BindingFlags.GetProperty | AllOfInstance );
129 if ( propInfo == null )
throw new ArgumentException( type.Name +
" does not contain property " + mName );
130 object mValue = propInfo.GetValue( obj, null );
131 mValue = LoadData( reader, mType, mValue );
132 propInfo.SetValue( obj, mValue, null );
136 FieldInfo fieldInfo = type.GetField( mName, BindingFlags.GetField | AllOfInstance );
137 if ( fieldInfo == null )
throw new ArgumentException( type.Name +
" does not contain field " + mName );
138 object mValue = fieldInfo.GetValue( obj );
139 mValue = LoadData( reader, mType, mValue );
140 fieldInfo.SetValue( obj, mValue );
143 else if ( reader.Name ==
"SerializedObject" )
148 object objValue = null;
150 using ( MemoryStream dataStream =
new MemoryStream( Encoding.Unicode.GetBytes( reader.Value ) ) )
152 XmlSerializer serializer =
new XmlSerializer( type );
153 objValue = serializer.Deserialize( dataStream );
156 while ( !reader.EOF && reader.NodeType != XmlNodeType.EndElement ) reader.Read();
160 else if ( reader.Name ==
"Value" )
165 obj = Enum.Parse( type, reader.Value,
false );
167 obj = GenParse( type, reader.Value );
169 while ( !reader.EOF && reader.NodeType != XmlNodeType.EndElement ) reader.Read();
171 else if ( reader.Name ==
"Array" )
174 obj = LoadArray( reader, mType, obj );
176 else if ( reader.Name ==
"List" )
179 int itemCount =
int.Parse( reader.GetAttribute(
"Count" ) );
180 obj = LoadList( reader, mType, itemCount, obj );
184 if ( metadata != null )
186 foreach ( KeyValuePair<string, string> entry
in metadata )
187 applyMetadata( type, obj, entry.Key, entry.Value );
193 private void applyMetadata( Type type,
object obj,
string tag,
string value )
201 if ( tag ==
"AddedToGame" && tagTrue( value ) && !gobj.
IsAddedToGame )
207 private bool tagTrue(
string value )
209 return value ==
"1" || value.ToLower() ==
"true";
212 internal void SaveData( XmlWriter writer, Type type,
object obj,
bool saveAllFields )
216 SaveArray( writer, type, obj );
222 SaveList( writer, type, obj );
228 writer.WriteElementString(
"Value", ( obj as Type ).AssemblyQualifiedName );
231 bool hasSaveAttrib = saveAllFields || type.GetCustomAttributes( typeof(
SaveAttribute ),
true ).Length > 0;
232 bool hasSaveAllFields = saveAllFields || type.GetCustomAttributes( typeof(
SaveAllFieldsAttribute ),
true ).Length > 0;
234 if ( type.IsClass && type != typeof(
string ) && !hasSaveAttrib )
237 if ( !hasSaveAttrib || ( type.IsPrimitive && type.IsEnum ) )
239 writer.WriteElementString(
"Value", GenToString( type, obj ) );
243 writeMetadata( writer, type, obj );
245 foreach ( PropertyInfo prop
in type.GetProperties( BindingFlags.GetProperty | AllOfInstance ) )
247 if ( IsIllegalType( prop.PropertyType ) )
250 object[] attribs = prop.GetCustomAttributes(
true );
251 if ( prop.GetCustomAttributes( typeof(
SaveAttribute ),
true ).Length == 0 )
254 object propValue = prop.GetValue( obj, null );
256 if ( propValue == null )
259 Type st = propValue.GetType();
260 SaveMember( writer,
"Property", st, prop, propValue, saveAllFields );
263 foreach ( FieldInfo field
in type.GetFields( BindingFlags.GetField | AllOfInstance ) )
265 if ( IsIllegalType( field.FieldType ) )
268 if ( !hasSaveAllFields && field.GetCustomAttributes( typeof(
SaveAttribute ),
true ).Length == 0 )
271 object fieldValue = field.GetValue( obj );
273 if ( fieldValue == null )
276 Type st = fieldValue.GetType();
277 SaveMember( writer,
"Field", st, field, fieldValue, saveAllFields );
281 private bool IsIllegalType( Type type )
283 return ( type == typeof( IntPtr ) || type == typeof( UIntPtr ) );
286 private void SaveMember( XmlWriter writer,
string elementName, Type memberType, MemberInfo member,
object memberValue,
bool saveAllFields )
288 writer.WriteStartElement( elementName );
289 writer.WriteAttributeString(
"Name", member.Name );
291 SaveData( writer, memberType, memberValue, saveAllFields || member.GetCustomAttributes( typeof(
SaveAllFieldsAttribute ),
true ).Length > 0 );
292 writer.WriteEndElement();
295 private void writeMetadata( XmlWriter writer, Type type,
object obj )
300 writer.WriteStartElement(
"Meta" );
301 writer.WriteAttributeString(
"AddedToGame",
"1" );
302 writer.WriteEndElement();
307 internal object LoadArray( XmlReader reader, Type containerType,
object obj )
309 Type designatedItemType = null;
310 Array array = (Array)obj;
313 for (
int readItems = 0;
314 readItems < array.GetLength( 0 ) &&
315 reader.Read() && !( reader.NodeType == XmlNodeType.EndElement && reader.Name ==
"Array" ); )
317 if ( reader.NodeType != XmlNodeType.Element )
319 if ( reader.Name !=
"Item" )
321 string name = reader.GetAttribute(
"Name" );
322 if ( name == null ) name =
"(undefined)";
323 throw new XmlException(
"Unexpected subelement in List block: " + reader.Name +
", Name = " + name );
326 index = Int16.Parse( reader.GetAttribute(
"Index" ) );
327 designatedItemType =
TypeHelper.
Parse( reader.GetAttribute(
"Type" ) );
329 object item = array.GetValue( index );
332 Type realItemType = item.GetType();
333 if ( designatedItemType != realItemType )
334 throw new XmlException(
"Array item type mismatch: expected " + designatedItemType.Name +
", got " + realItemType.Name +
" at index " + index.ToString() );
337 item = LoadData( reader, designatedItemType, item );
338 array.SetValue( item, index );
346 private void FixListSize( ref IList list,
int itemCount )
348 while ( list.Count < itemCount )
353 while ( list.Count > itemCount )
355 list.RemoveAt( list.Count - 1 );
359 internal object LoadList( XmlReader reader, Type containerType,
int itemCount,
object obj )
361 object[] listObjects =
new object[itemCount];
362 IList list = (IList)obj;
364 while ( list.Count > itemCount )
366 int removeIndex = list.Count - 1;
369 ( (Destroyable)( list[removeIndex] ) ).Destroy();
371 list.RemoveAt( removeIndex );
374 for (
int i = 0; i < Math.Min( itemCount, list.Count ); i++ )
375 listObjects[i] = list[i];
376 for (
int i = list.Count; i < itemCount; i++ )
377 listObjects[i] = null;
379 while ( reader.Read() && !( reader.NodeType == XmlNodeType.EndElement && reader.Name ==
"List" ) )
381 if ( reader.NodeType != XmlNodeType.Element )
383 if ( reader.Name !=
"Item" )
385 string name = reader.GetAttribute(
"Name" );
386 if ( name == null ) name =
"(undefined)";
387 throw new XmlException(
"Unexpected subelement in List block: " + reader.Name +
", Name = " + name );
390 string tag = reader.GetAttribute(
"Tag" );
392 int itemindex =
int.Parse( reader.GetAttribute(
"Index" ) );
394 if ( tag != null && listObjects[itemindex] == null )
396 if ( !TryCreateObject( itemType, tag, out listObjects[itemindex] ) )
397 throw new MissingMethodException( String.Format(
"No factory method for type {0}, tag {1}", itemType.Name, tag) );
400 listObjects[itemindex] = LoadData( reader, itemType, listObjects[itemindex] );
405 for (
int i = 0; i < listObjects.Length; i++ )
406 list.Add( listObjects[i] );
411 bool TryCreateObject( Type type,
string tag, out
object obj )
413 if ( type == typeof(
string ) )
424 obj =
Factory.FactoryCreate( type, tag );
427 catch ( KeyNotFoundException )
432 obj = Activator.CreateInstance( type,
true );
435 catch ( MissingMethodException )
444 internal void SaveArray( XmlWriter writer, Type containerType,
object obj )
446 Array array = (Array)obj;
448 writer.WriteStartElement(
"Array" );
451 for (
int i = 0; i < array.GetLength( 0 ); i++ )
453 object item = array.GetValue( i );
454 Type realItemType = item.GetType();
455 writer.WriteStartElement(
"Item" );
456 writer.WriteAttributeString(
"Index", i.ToString() );
458 if ( item is
Tagged ) writer.WriteAttributeString(
"Tag", ( (Tagged)item ).Tag.ToString() );
459 SaveData( writer, realItemType, item,
false );
460 writer.WriteEndElement();
463 writer.WriteEndElement();
466 internal void SaveList( XmlWriter writer, Type containerType,
object obj )
468 IList list = (IList)obj;
470 writer.WriteStartElement(
"List" );
472 writer.WriteAttributeString(
"Count", list.Count.ToString() );
474 for (
int i = 0; i < list.Count; i++ )
476 Type realItemType = list[i].GetType();
477 writer.WriteStartElement(
"Item" );
479 writer.WriteAttributeString(
"Index", i.ToString() );
480 if ( list[i] is
Tagged ) writer.WriteAttributeString(
"Tag", ( (Tagged)list[i] ).Tag.ToString() );
481 SaveData( writer, realItemType, list[i],
false );
482 writer.WriteEndElement();
485 writer.WriteEndElement();
bool IsAddedToGame
Onko olio lisätty peliin.
Rajapinta olioille, joilla on Tag-ominaisuus.
void Add(IGameObject o)
Lisää olion peliin. Tavalliset oliot tulevat automaattisesti kerrokselle 0 ja ruutuoliot päällimmäise...
Peliluokka reaaliaikaisille peleille.
static bool InheritsFrom(Type actual, Type expected)
static string ToString(Type type)
static Type Parse(string typeStr)
Pelialueella liikkuva olio. Käytä fysiikkapeleissä PhysicsObject-olioita.
Rajapinta olioille, jotka ovat tuhottavissa.