private void EnsureInitialized() { if (_initialized) { return; } _initialized = true; _declaredNameToField = Fields.ToDictionary(v => v.Name); _declaredNameToMethods = new Dictionary <string, frMethod[]>(); AppendMultiDict(_declaredNameToMethods, Methods, v => v.RawMethod.Name); _declaredPredicateToFields = new Dictionary <frIPredicate, frField[]>(); _declaredPredicateToMethods = new Dictionary <frIPredicate, frMethod[]>(); _flattenedNameToFields = new Dictionary <string, frField[]>(); _flattenedNameToMethods = new Dictionary <string, frMethod[]>(); _flattenedPredicateToFields = new Dictionary <frIPredicate, frField[]>(); _flattenedPredicateToMethods = new Dictionary <frIPredicate, frMethod[]>(); frType type = this; while (type != null) { AppendMultiDict(_flattenedNameToFields, type.Fields, v => v.Name); AppendMultiDict(_flattenedNameToMethods, type.Methods, v => v.RawMethod.Name); type = type.Parent; } }
public void FrTypesAreCached() { var manager = new frManager(); frType myDerivedType = manager.Get(typeof(MyDerivedType)); Assert.IsTrue(ReferenceEquals(myDerivedType, manager.Get(typeof(MyDerivedType)))); Assert.IsTrue(ReferenceEquals(myDerivedType.Parent, manager.Get(typeof(MyBaseType)))); }
public void TestLookupWithOverloadedMethod() { var manager = new frManager(); frType myDerivedType = manager.Get(typeof(MyDerivedType)); frMethod[] methods = myDerivedType.GetDeclaredMethodsByName("ChildMethod"); Assert.IsTrue(methods.Length == 2); Assert.AreEqual(methods[0].RawMethod.Name, methods[1].RawMethod.Name); Assert.AreNotEqual(methods[0], methods[1]); Assert.AreNotEqual(methods[0].RawMethod.GetParameters().Length, methods[1].RawMethod.GetParameters().Length); }
public void TestLookupWithNewFields() { var manager = new frManager(); frType myDerivedType = manager.Get(typeof(MyDerivedType)); frType myBaseType = manager.Get(typeof(MyBaseType)); // new fields Assert.AreEqual(typeof(MyDerivedType), myDerivedType.GetDeclaredFieldByName("BaseField").RawMember.DeclaringType); Assert.AreEqual(typeof(MyBaseType), myBaseType.GetDeclaredFieldByName("BaseField").RawMember.DeclaringType); CollectionAssert.AreEquivalent(new[] { myDerivedType.GetDeclaredFieldByName("BaseField"), myBaseType.GetDeclaredFieldByName("BaseField") }, myDerivedType.GetFlattenedFieldsByName("BaseField")); }
public void TestInterfaces() { var manager = new frManager(); frType myBaseType = manager.Get(typeof(MyBaseType)); frType myDerivedType = manager.Get(typeof(MyDerivedType)); CollectionAssert.AreEquivalent(new[] { typeof(IBaseInterface), typeof(IExplicitInterface) }, Interfaces(myBaseType)); CollectionAssert.AreEquivalent(new[] { typeof(IDerivedInterface), typeof(IBaseInterface), typeof(IExplicitInterface) }, Interfaces(myDerivedType)); CallCounts.MyBaseType_MyExplicitMethodCallCount = 0; myBaseType.GetInterface <IExplicitInterface>().GetDeclaredMethodsByName("MyExplicitMethod")[0].Invoke(new MyBaseType(), null); Assert.AreEqual(1, CallCounts.MyBaseType_MyExplicitMethodCallCount); CallCounts.MyDerivedType_MyExplicitMethodCallCount = 0; myDerivedType.GetInterface <IExplicitInterface>().GetDeclaredMethodsByName("MyExplicitMethod")[0].Invoke(new MyDerivedType(), null); Assert.AreEqual(1, CallCounts.MyDerivedType_MyExplicitMethodCallCount); }
public void TestLocalDeclaration() { var manager = new frManager(); frType myDerivedType = manager.Get(typeof(MyDerivedType)); // Verify parent/rawtype Assert.AreEqual(typeof(MyDerivedType), myDerivedType.RawType); Assert.AreEqual(typeof(MyBaseType), myDerivedType.Parent.RawType); // Verify fields/methods // MyDerivedType CollectionAssert.AreEquivalent(new[] { "BaseField", "ChildField" }, DeclaredFieldNames(myDerivedType)); CollectionAssert.AreEquivalent(new[] { "BaseChildMethod", "ChildMethod", "ChildMethod", "FastReflect.IExplicitInterface.MyExplicitMethod" }, DeclaredMethodNames(myDerivedType)); // MyBaseType CollectionAssert.AreEquivalent(new[] { "BaseField" }, DeclaredFieldNames(myDerivedType.Parent)); CollectionAssert.AreEquivalent(new[] { "BaseMethod", "BaseVirtualMethod", "FastReflect.IExplicitInterface.MyExplicitMethod" }, DeclaredMethodNames(myDerivedType.Parent)); }
public frMethod[] GetFlattenedMethodsByPredicate(frIPredicate predicate) { EnsureInitialized(); frMethod[] result; if (!_flattenedPredicateToMethods.TryGetValue(predicate, out result)) { var members = new List <frMethod>(); frType type = this; while (type != null) { RunPredicate(predicate, type.Methods, members); type = type.Parent; } _flattenedPredicateToMethods[predicate] = result = members.ToArray(); } return(result); }
public frField[] GetFlattenedFieldsByPredicate(frIPredicate predicate) { EnsureInitialized(); frField[] result; if (!_flattenedPredicateToFields.TryGetValue(predicate, out result)) { var fields = new List <frField>(); frType type = this; while (type != null) { RunPredicate(predicate, type.Fields, fields); type = type.Parent; } _flattenedPredicateToFields[predicate] = result = fields.ToArray(); } return(result); }
public frType Get(Type type) { frType result; if (_typeToFrTypeCache.TryGetValue(type, out result) == false) { result = new frType(); // Immediately insert result into the cache so if there are any // cyclic calls we resolve to |result|. _typeToFrTypeCache[type] = result; result.RawType = type; if (type.Resolve().BaseType != null) { result.Parent = Get(type.Resolve().BaseType); } result.Interfaces = type.GetInterfaces().Select(t => Get(t)).ToArray(); GetFieldsAndMethods(type, out result.Fields, out result.Methods); } return(result); }
public void Sanity() { var manager = new frManager(); // Verify built in types are supported. Assert.IsNotNull(manager.Get(typeof(object))); Assert.IsNotNull(manager.Get(typeof(int))); // Verify custom types are supported. frType myBaseType = manager.Get(typeof(MyBaseType)); Assert.IsNotNull(myBaseType); // fields/methods on MyTest Assert.AreEqual(typeof(MyBaseType), myBaseType.RawType); CollectionAssert.AreEquivalent(new[] { "BaseField" }, DeclaredFieldNames(myBaseType)); CollectionAssert.AreEquivalent(new[] { "BaseMethod", "BaseVirtualMethod", "FastReflect.IExplicitInterface.MyExplicitMethod" }, DeclaredMethodNames(myBaseType)); // parent type is Object Assert.AreEqual(typeof(object), myBaseType.Parent.RawType); }
public void TestAcceleration() { var manager = new frManager(typeof(AccelerationProvider)); frType accelerationType = manager.Get(typeof(AccelerationType)); var instance = new AccelerationType(); instance.Field = 10; CallCounts.Accelerated = 0; accelerationType.GetDeclaredMethodsByName("Method")[0].Invoke(instance, null); Assert.AreEqual(1, CallCounts.Accelerated); CallCounts.Accelerated = 0; Assert.AreEqual(10, accelerationType.GetDeclaredFieldByName("Field").Read <object>(instance)); Assert.AreEqual(1, CallCounts.Accelerated); CallCounts.Accelerated = 0; accelerationType.GetDeclaredFieldByName("Field").Write(ref instance, 20f); Assert.AreEqual(20f, instance.Field); Assert.AreEqual(1, CallCounts.Accelerated); }
private static IEnumerable <Type> Interfaces(frType type) { return(type.Interfaces.Select(t => t.RawType)); }
private static IEnumerable <string> DeclaredMethodNames(frType type) { return(type.Methods.Select(m => m.RawMethod.Name)); }
private static IEnumerable <string> DeclaredFieldNames(frType type) { return(type.Fields.Select(f => f.Name)); }
public void TestAccelerationPerformanceDifference() { if (!frConfig.HasJit) { return; } frConfig.HasJit = false; frType reflectedMyBaseType = (new frManager()).Get(typeof(AccelerationType)); frMethod reflectedMethod = reflectedMyBaseType.GetDeclaredMethodsByName("Method")[0]; frField reflectedField = reflectedMyBaseType.GetDeclaredFieldByName("Field"); frConfig.HasJit = true; frType jitMyBaseType = (new frManager()).Get(typeof(AccelerationType)); frMethod jitMethod = jitMyBaseType.GetDeclaredMethodsByName("Method")[0]; frField jitField = jitMyBaseType.GetDeclaredFieldByName("Field"); frType aotMyBaseType = (new frManager(typeof(AccelerationProvider))).Get(typeof(AccelerationType)); frMethod aotMethod = aotMyBaseType.GetDeclaredMethodsByName("Method")[0]; frField aotField = aotMyBaseType.GetDeclaredFieldByName("Field"); const int ITERATION_COUNT = 50000; var instance = new AccelerationType(); // SECTION: Method calls. { var reflectedTime = Stopwatch.StartNew(); for (int i = 0; i < ITERATION_COUNT; ++i) { reflectedMethod.Invoke(instance, null); } reflectedTime.Stop(); var jitTime = Stopwatch.StartNew(); for (int i = 0; i < ITERATION_COUNT; ++i) { jitMethod.Invoke(instance, null); } jitTime.Stop(); var aotTime = Stopwatch.StartNew(); for (int i = 0; i < ITERATION_COUNT; ++i) { aotMethod.Invoke(instance, null); } aotTime.Stop(); Console.WriteLine(string.Format("Invoke method ticks: Reflected={0}, Jit={1}, Aot={2}", reflectedTime.ElapsedTicks, jitTime.ElapsedTicks, aotTime.ElapsedTicks)); UnityEngine.Debug.Log(string.Format("Invoke method ticks: Reflected={0}, Jit={1}, Aot={2}", reflectedTime.ElapsedTicks, jitTime.ElapsedTicks, aotTime.ElapsedTicks)); } // SECTION: Field reads { var reflectedTime = Stopwatch.StartNew(); for (int i = 0; i < ITERATION_COUNT; ++i) { reflectedField.Read <float>(instance); } reflectedTime.Stop(); var jitTime = Stopwatch.StartNew(); for (int i = 0; i < ITERATION_COUNT; ++i) { jitField.Read <float>(instance); } jitTime.Stop(); var aotTime = Stopwatch.StartNew(); for (int i = 0; i < ITERATION_COUNT; ++i) { aotField.Read <float>(instance); } aotTime.Stop(); Console.WriteLine(string.Format("Read field ticks: Reflected={0}, Jit={1}, Aot={2}", reflectedTime.ElapsedTicks, jitTime.ElapsedTicks, aotTime.ElapsedTicks)); UnityEngine.Debug.Log(string.Format("Read field ticks: Reflected={0}, Jit={1}, Aot={2}", reflectedTime.ElapsedTicks, jitTime.ElapsedTicks, aotTime.ElapsedTicks)); // aot/jit should be at least 2x as fast as reflection // It is usually a 5-10x performance difference, but there can be a lot of natural variation. Assert.IsTrue(jitTime.ElapsedTicks * 2 < reflectedTime.ElapsedTicks); Assert.IsTrue(aotTime.ElapsedTicks * 2 < reflectedTime.ElapsedTicks); } }
public string GenerateForType(string providerTypeName, frType type) { var w = new Helper() { result = new StringBuilder() }; string typeName = type.RawType.CSharpName(/*includeNamespace:*/ true); w.W(0, "// ***************************************************************************"); w.W(0, "// ***************************************************************************"); w.W(0, "// *** WARNING: This file was automatically generated by FastReflect. ***"); w.W(0, "// *** Manual edits may get overwritten. ***"); w.W(0, "// ***************************************************************************"); w.W(0, "// ***************************************************************************"); w.W(0, ""); w.W(0, "using System;"); w.W(0, "using FastReflect;"); w.W(0, ""); w.W(0, "public partial class {0} {{", providerTypeName); w.W(1, "public static frTypeAotData Provider_{0} = new frTypeAotData {{", type.RawType.CSharpName(/*includeNamespace:*/ true, /*ensureSafeDeclarationName:*/ true)); w.W(2, "ProviderFor = typeof({0}),", typeName); w.W(2, "FieldAotData = new frField.AotData[] {{"); foreach (frField field in type.Fields) { /* * new frField.AotData { * FieldName = "Field", * Read = (o) => { ((AccelerationType)o).Field; }, * Write = (ref object o, object v) => { var u = (AccelerationType)o; u.Field = (float)v; o = u; } * } */ w.W(3, "new frField.AotData {{"); w.W(4, "FieldName = \"{0}\",", field.Name); w.W(4, "Read = (o) => (({0})o).{1},", typeName, field.Name); if (type.RawType.Resolve().IsValueType) { w.W(4, "Write = (ref object o, object v) => {{ var u = ({0})o; u.{1} = ({2})v; o = u; }}", typeName, field.Name, field.MemberType.CSharpName(/*includeNamespace:*/ true)); } else { w.W(4, "Write = (ref object o, object v) => (({0})o).{1} = ({2})v", typeName, field.Name, field.MemberType.CSharpName(/*includeNamespace:*/ true)); } w.W(3, "}},"); } w.W(2, "}},"); w.W(2, "MethodAotData = new frMethod.AotData[] {{"); foreach (frMethod method in type.Methods) { /* * new frMethod.AotData { * MethodName = "Method", * Parameters = new Type[] {}, * Invoke = (o, args) => { return ((AccelerationType)o).Method(); } * }, */ w.W(3, "new frMethod.AotData {{"); w.W(4, "MethodName = \"{0}\",", method.RawMethod.Name); var parameters = method.RawMethod.GetParameters(); if (parameters.Length > 0) { // typeof(int), typeof(double) var paramTypes = string.Join(", ", parameters.Select(p => "typeof(" + p.ParameterType.CSharpName(/*includeNamespace:*/ true) + ")").ToArray()); w.W(4, "Parameters = new Type[] {{ {0} }},", paramTypes); } else { w.W(4, "Parameters = Type.EmptyTypes,"); } // (int)args[0], (double)args[1] string unpackArgs = string.Join(", ", Enumerable.Range(0, method.RawMethod.GetParameters().Length).Select(p => "(" + parameters[p].ParameterType.CSharpName(/*includeNamespace*/ true) + ")args[" + p + "]").ToArray()); string methodHolderTypeName = typeName; string methodName = method.RawMethod.Name; if (methodName.Contains(".")) { // Explicit method. We need to cast to the correct type. methodHolderTypeName = methodName.Substring(0, methodName.LastIndexOf(".")); methodName = method.RawMethod.Name.Substring(methodName.LastIndexOf(".") + 1); } if (method.RawMethod.ReturnType == typeof(void)) { w.W(4, "Invoke = (o, args) => {{ (({0})o).{1}({2}); return null; }}", methodHolderTypeName, methodName, unpackArgs); } else { w.W(4, "Invoke = (o, args) => (({0})o).{1}({2})", methodHolderTypeName, methodName, unpackArgs); } w.W(3, "}},"); } w.W(2, "}},"); w.W(1, "}};"); w.W(0, "}}"); return(w.result.ToString()); }