예제 #1
0
        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;
            }
        }
예제 #2
0
        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))));
        }
예제 #3
0
        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);
        }
예제 #4
0
        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"));
        }
예제 #5
0
        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);
        }
예제 #6
0
        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));
        }
예제 #7
0
 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);
 }
예제 #8
0
 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);
 }
예제 #9
0
        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);
        }
예제 #10
0
        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);
        }
예제 #11
0
        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);
        }
예제 #12
0
 private static IEnumerable <Type> Interfaces(frType type)
 {
     return(type.Interfaces.Select(t => t.RawType));
 }
예제 #13
0
 private static IEnumerable <string> DeclaredMethodNames(frType type)
 {
     return(type.Methods.Select(m => m.RawMethod.Name));
 }
예제 #14
0
 private static IEnumerable <string> DeclaredFieldNames(frType type)
 {
     return(type.Fields.Select(f => f.Name));
 }
예제 #15
0
        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);
            }
        }
예제 #16
0
        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());
        }