Show More
Commit Description:
Add timers for Simulation and various engines...
Commit Description:
Add timers for Simulation and various engines Starting to add additional timers for different stages of the process of updating in order to get more insight into what is slowing it down. The update takes 9ms, which is much longer than it used to. Engine-specific timers are coming later.
File last commit:
Show/Diff file:
Action:
FNA/src/Content/ContentReaders/ReflectiveReader.cs
300 lines | 6.5 KiB | text/x-csharp | CSharpLexer
#region License
/* FNA - XNA4 Reimplementation for Desktop Platforms
* Copyright 2009-2020 Ethan Lee and the MonoGame Team
*
* Released under the Microsoft Public License.
* See LICENSE for details.
*/
#endregion
#region Using Statements
using System;
using System.Collections.Generic;
using System.Reflection;
#endregion
namespace Microsoft.Xna.Framework.Content
{
internal class ReflectiveReader<T> : ContentTypeReader
{
#region Reader Delegates
delegate void ReadElement(ContentReader input, object parent);
private List<ReadElement> readers;
#endregion
#region Public Properties
public override bool CanDeserializeIntoExistingObject
{
get
{
return TargetType.IsClass;
}
}
#endregion
#region Private Variables
private ConstructorInfo constructor;
private ContentTypeReader baseTypeReader;
#endregion
#region Internal Constructor
internal ReflectiveReader() : base(typeof(T))
{
}
#endregion
#region Protected ContentTypeReader Methods
protected internal override void Initialize(ContentTypeReaderManager manager)
{
base.Initialize(manager);
Type baseType = TargetType.BaseType;
if (baseType != null && baseType != typeof(object))
{
baseTypeReader = manager.GetTypeReader(baseType);
}
constructor = TargetType.GetDefaultConstructor();
const BindingFlags attrs = (
BindingFlags.NonPublic |
BindingFlags.Public |
BindingFlags.Instance |
BindingFlags.DeclaredOnly
);
/* Sometimes, overridden properties of abstract classes can show up even with
* BindingFlags.DeclaredOnly is passed to GetProperties. Make sure that
* all properties in this list are defined in this class by comparing
* its get method with that of its base class. If they're the same
* Then it's an overridden property.
*/
PropertyInfo[] properties = TargetType.GetProperties(attrs);
FieldInfo[] fields = TargetType.GetFields(attrs);
readers = new List<ReadElement>(fields.Length + properties.Length);
// Gather the properties.
foreach (PropertyInfo property in properties)
{
MethodInfo pm = property.GetGetMethod(true);
if (pm == null || pm != pm.GetBaseDefinition())
{
continue;
}
ReadElement read = GetElementReader(manager, property);
if (read != null)
{
readers.Add(read);
}
}
// Gather the fields.
foreach (FieldInfo field in fields)
{
ReadElement read = GetElementReader(manager, field);
if (read != null)
{
readers.Add(read);
}
}
}
protected internal override object Read(ContentReader input, object existingInstance)
{
T obj;
if (existingInstance != null)
{
obj = (T) existingInstance;
}
else
{
if (constructor == null)
{
obj = (T) Activator.CreateInstance(typeof(T));
}
else
{
obj = (T) constructor.Invoke(null);
}
}
if (baseTypeReader != null)
{
baseTypeReader.Read(input, obj);
}
// Box the type.
object boxed = (object) obj;
foreach (ReadElement reader in readers)
{
reader(input, boxed);
}
// Unbox it... required for value types.
obj = (T) boxed;
return obj;
}
#endregion
#region Private Static Methods
private static ReadElement GetElementReader(
ContentTypeReaderManager manager,
MemberInfo member
) {
PropertyInfo property = member as PropertyInfo;
FieldInfo field = member as FieldInfo;
if (property != null)
{
// Properties must have at least a getter.
if (property.CanRead == false)
{
return null;
}
// Skip over indexer properties
if (property.GetIndexParameters().Length > 0)
{
return null;
}
}
// Are we explicitly asked to ignore this item?
Attribute attr = Attribute.GetCustomAttribute(
member,
typeof(ContentSerializerIgnoreAttribute)
);
if (attr != null)
{
return null;
}
ContentSerializerAttribute contentSerializerAttribute = Attribute.GetCustomAttribute(
member,
typeof(ContentSerializerAttribute)
) as ContentSerializerAttribute;
if (contentSerializerAttribute == null)
{
if (property != null)
{
/* There is no ContentSerializerAttribute, so non-public
* properties cannot be deserialized.
*/
MethodInfo getMethod = property.GetGetMethod(true);
if (getMethod != null && !getMethod.IsPublic)
{
return null;
}
MethodInfo setMethod = property.GetSetMethod(true);
if (setMethod != null && !setMethod.IsPublic)
{
return null;
}
/* If the read-only property has a type reader,
* and CanDeserializeIntoExistingObject is true,
* then it is safe to deserialize into the existing object.
*/
if (!property.CanWrite)
{
ContentTypeReader typeReader = manager.GetTypeReader(property.PropertyType);
if (typeReader == null || !typeReader.CanDeserializeIntoExistingObject)
{
return null;
}
}
}
else
{
/* There is no ContentSerializerAttribute, so non-public
* fields cannot be deserialized.
*/
if (!field.IsPublic)
{
return null;
}
// evolutional: Added check to skip initialise only fields
if (field.IsInitOnly)
{
return null;
}
}
}
Action<object, object> setter;
Type elementType;
if (property != null)
{
elementType = property.PropertyType;
if (property.CanWrite)
{
setter = (o, v) => property.SetValue(o, v, null);
}
else
{
setter = (o, v) => { };
}
}
else
{
elementType = field.FieldType;
setter = field.SetValue;
}
if ( contentSerializerAttribute != null &&
contentSerializerAttribute.SharedResource )
{
return (input, parent) =>
{
Action<object> action = value => setter(parent, value);
input.ReadSharedResource(action);
};
}
// We need to have a reader at this point.
ContentTypeReader reader = manager.GetTypeReader(elementType);
if (reader == null)
{
throw new ContentLoadException(string.Format(
"Content reader could not be found for {0} type.",
elementType.FullName
));
}
/* We use the construct delegate to pick the correct existing
* object to be the target of deserialization.
*/
Func<object, object> construct = parent => null;
if (property != null && !property.CanWrite)
{
construct = parent => property.GetValue(parent, null);
}
return (input, parent) =>
{
object existing = construct(parent);
object obj2 = input.ReadObject(reader, existing);
setter(parent, obj2);
};
}
#endregion
}
}