コード例 #1
0
ファイル: FastReflectionFactories.cs プロジェクト: mer2/devfx
 static FastReflectionFactories()
 {
     MethodInvokerFactory = new MethodInvokerFactory();
     PropertyAccessorFactory = new PropertyAccessorFactory();
     FieldAccessorFactory = new FieldAccessorFactory();
     ConstructorInvokerFactory = new ConstructorInvokerFactory();
 }
コード例 #2
0
        public void Create_IfMultipleInputParameters_PassesInputArguments(bool isInstance)
        {
            // Arrange
            MethodInfo method    = GetMethodInfo(isInstance, "TestIntStringObjectArray");
            int        expectedA = 1;
            string     expectedB = "B";

            object[] expectedC = new object[] { new object() };

            // Act
            IMethodInvoker <MethodInvokerFactoryTests, object> invoker =
                MethodInvokerFactory.Create <MethodInvokerFactoryTests, object>(method);

            // Assert
            Assert.NotNull(invoker);
            bool callbackCalled = false;
            Action <int, string, object> callback = (a, b, c) =>
            {
                callbackCalled = true;
                Assert.Equal(expectedA, a);
                Assert.Same(expectedB, b);
                Assert.Same(expectedC, c);
            };
            MethodInvokerFactoryTests instance = GetInstance(isInstance);

            object[] arguments = new object[] { expectedA, expectedB, expectedC, callback };
            invoker.InvokeAsync(instance, arguments).GetAwaiter().GetResult();
            Assert.True(callbackCalled);
        }
コード例 #3
0
        public void Create_IfInOutByRefMethodReturnsTask_RoundtripsArguments(bool isInstance)
        {
            // Arrange
            MethodInfo method           = GetMethodInfo(isInstance, "TestInOutByRefReturnTask");
            int        expectedA        = 1;
            string     expectedInitialB = "B";
            string     expectedFinalB   = "b";

            object[] expectedC = new object[] { new object(), default(int), String.Empty };

            // Act
            IMethodInvoker <MethodInvokerFactoryTests, object> invoker =
                MethodInvokerFactory.Create <MethodInvokerFactoryTests, object>(method);

            // Assert
            Assert.NotNull(invoker);
            bool             callbackCalled = false;
            InOutRefTaskFunc callback       = delegate(int a, ref string b, out object[] c)
            {
                callbackCalled = true;
                Assert.Equal(expectedA, a);
                Assert.Same(expectedInitialB, b);
                b = expectedFinalB;
                c = expectedC;
                return(Task.FromResult(0));
            };
            MethodInvokerFactoryTests instance = GetInstance(isInstance);

            object[] arguments = new object[] { expectedA, expectedInitialB, null, callback };
            invoker.InvokeAsync(instance, arguments).GetAwaiter().GetResult();
            Assert.True(callbackCalled);
            Assert.Same(expectedFinalB, arguments[1]);
            Assert.Same(expectedC, arguments[2]);
        }
コード例 #4
0
        public void Create_IfMultipleOutputParameters_SetsOutputArguments(bool isInstance)
        {
            // Arrange
            MethodInfo method    = GetMethodInfo(isInstance, "TestOutIntStringObjectArray");
            int        expectedA = 1;
            string     expectedB = "B";

            object[] expectedC = new object[] { new object() };

            // Act
            IMethodInvoker <MethodInvokerFactoryTests, object> invoker =
                MethodInvokerFactory.Create <MethodInvokerFactoryTests, object>(method);

            // Assert
            Assert.NotNull(invoker);
            bool      callbackCalled = false;
            OutAction callback       = delegate(out int a, out string b, out object[] c)
            {
                callbackCalled = true;
                a = expectedA;
                b = expectedB;
                c = expectedC;
            };
            MethodInvokerFactoryTests instance = GetInstance(isInstance);

            object[] arguments = new object[] { default(int), null, null, callback };
            invoker.InvokeAsync(instance, arguments).GetAwaiter().GetResult();
            Assert.True(callbackCalled);
            Assert.Equal(expectedA, arguments[0]);
            Assert.Same(expectedB, arguments[1]);
            Assert.Same(expectedC, arguments[2]);
        }
コード例 #5
0
        public void Create_IfMethodReturnsNonTask_Throws()
        {
            // Arrange
            MethodInfo method = GetMethodInfo("ReturnInt");

            // Act & Assert
            ExceptionAssert.ThrowsNotSupported(() => MethodInvokerFactory.Create <MethodInvokerFactoryTests>(method),
                                               "Methods may only return void or Task.");
        }
コード例 #6
0
        public void Create_IfTReflectedIsNotReflectedType_Throws(bool isInstance)
        {
            // Arrange
            MethodInfo method = GetMethodInfo(isInstance, "ReturnVoid");

            // Act & Assert
            ExceptionAssert.ThrowsInvalidOperation(() => MethodInvokerFactory.Create <object>(method),
                                                   "TReflected must match the method's ReflectedType.");
        }
コード例 #7
0
        public void Create_IfMethodIsNull_Throws()
        {
            // Arrange
            MethodInfo method = null;

            // Act & Assert
            ExceptionAssert.ThrowsArgumentNull(() => MethodInvokerFactory.Create <MethodInvokerFactoryTests>(method),
                                               "method");
        }
コード例 #8
0
        /// <summary>
        /// 根据指定的MethodInfo以及参数数组,快速调用相关的方法。
        /// </summary>
        /// <param name="methodInfo">MethodInfo实例成员</param>
        /// <param name="obj">目标实例成员</param>
        /// <param name="parameters">函数参数</param>
        /// <returns>调用结果</returns>
        public static object FastInvoke(this MethodInfo methodInfo, object obj, params object[] parameters)
        {
            if (methodInfo == null)
            {
                throw new ArgumentNullException("methodInfo");
            }

            IInvokeMethod method = MethodInvokerFactory.GetMethodInvokerWrapper(methodInfo);

            return(method.Invoke(obj, parameters));
        }
コード例 #9
0
        public void Create_IfStaticMethodReturnsVoid_ReturnsVoidInvoker(bool isInstance)
        {
            // Arrange
            MethodInfo method = GetMethodInfo(isInstance, "ReturnVoid");

            // Act
            IMethodInvoker <MethodInvokerFactoryTests, object> invoker =
                MethodInvokerFactory.Create <MethodInvokerFactoryTests, object>(method);

            // Assert
            Assert.IsType <VoidMethodInvoker <MethodInvokerFactoryTests, object> >(invoker);
        }
コード例 #10
0
        public void Create_IfStaticMethodReturnsTask_ReturnsTaskInvoker(bool isInstance)
        {
            // Arrange
            MethodInfo method = GetMethodInfo(isInstance, "ReturnTask");

            // Act
            IMethodInvoker <MethodInvokerFactoryTests> invoker =
                MethodInvokerFactory.Create <MethodInvokerFactoryTests>(method);

            // Assert
            Assert.IsType <TaskMethodInvoker <MethodInvokerFactoryTests> >(invoker);
        }
コード例 #11
0
        private void CreateTimersFromAssemblies(long tick)
        {
            // Find methods with TimerAttribute in any ISystem in any assembly.
            var events = new AssemblyScanner()
                         .IncludeAllAssemblies()
                         .IncludeNonPublicMembers()
                         .Implements <ISystem>()
                         .ScanMethods <TimerAttribute>();

            // Create timer invokers and store timer info in registry.
            foreach (var(method, attribute) in events)
            {
                CoreLog.LogDebug("Adding timer on {0}.{1}.", method.DeclaringType, method.Name);

                if (!IsValidInterval(attribute.IntervalTimeSpan))
                {
                    CoreLog.Log(CoreLogLevel.Error, $"Timer {method} could not be registered the interval {attribute.IntervalTimeSpan} is invalid.");
                    continue;
                }

                var service = _serviceProvider.GetService(method.DeclaringType);

                if (service == null)
                {
                    CoreLog.Log(CoreLogLevel.Debug, "Skipping timer registration because service could not be loaded.");
                    continue;
                }

                var parameterInfos = method.GetParameters()
                                     .Select(info => new MethodParameterSource(info)
                {
                    IsService = true
                })
                                     .ToArray();

                var compiled = MethodInvokerFactory.Compile(method, parameterInfos);

                if (attribute.IntervalTimeSpan < LowInterval)
                {
                    CoreLog.Log(CoreLogLevel.Warning, $"Timer {method.DeclaringType}.{method.Name} has a low interval of {attribute.IntervalTimeSpan}.");
                }

                var timer = new TimerInfo
                {
                    IsActive      = true,
                    Invoke        = () => compiled(service, null, _serviceProvider, null),
                    IntervalTicks = attribute.IntervalTimeSpan.Ticks,
                    NextTick      = tick + attribute.IntervalTimeSpan.Ticks
                };

                _timers.Add(timer);
            }
        }
コード例 #12
0
        public void Create_IfReturnsTaskAndTaskCanceled_ReturnsCanceledTask(bool isInstance)
        {
            // Arrange
            MethodInfo method = GetMethodInfo(isInstance, "ReturnCanceledTask");

            // Act
            IMethodInvoker <MethodInvokerFactoryTests> invoker =
                MethodInvokerFactory.Create <MethodInvokerFactoryTests>(method);

            // Assert
            MethodInvokerFactoryTests instance = GetInstance(isInstance);
            Task task = invoker.InvokeAsync(instance, null);

            Assert.NotNull(task);
            task.WaitUntilCompleted();
            Assert.Equal(TaskStatus.Canceled, task.Status);
        }
コード例 #13
0
        public void Create_IfParameterlessMethod_CanInvoke(bool isInstance)
        {
            // Arrange
            MethodInfo method = GetMethodInfo(isInstance, "ParameterlessMethod");

            // Act
            IMethodInvoker <MethodInvokerFactoryTests> invoker =
                MethodInvokerFactory.Create <MethodInvokerFactoryTests>(method);

            try
            {
                // Assert
                MethodInvokerFactoryTests instance = GetInstance(isInstance);
                invoker.InvokeAsync(instance, null).GetAwaiter().GetResult();
                Assert.True(_parameterlessMethodCalled);
            }
            finally
            {
                _parameterlessMethodCalled = false;
            }
        }
コード例 #14
0
        private InvokerInfo CreateInvoker(MethodInfo method, MethodParameterSource[] parameterInfos,
                                          int callbackParamCount)
        {
            var compiled = MethodInvokerFactory.Compile(method, parameterInfos);

            return(new InvokerInfo
            {
                TargetType = method.DeclaringType,
                Invoke = (instance, eventContext) =>
                {
                    var args = eventContext.Arguments;
                    if (callbackParamCount == args.Length)
                    {
                        return compiled(instance, args, eventContext.EventServices, _entityManager);
                    }

                    CoreLog.Log(CoreLogLevel.Error,
                                $"Callback parameter count mismatch {callbackParamCount} != {args.Length}");
                    return null;
                }
            });
        }
コード例 #15
0
        public void Create_IfMultipleReferenceParameters_RoundtripsArguments(bool isInstance)
        {
            // Arrange
            MethodInfo method           = GetMethodInfo(isInstance, "TestByRefIntStringObjectArray");
            int        expectedInitialA = 1;
            string     expectedInitialB = "B";

            object[] expectedInitialC = new object[] { new object() };
            int      expectedFinalA   = 2;
            string   expectedFinalB   = "b";

            object[] expectedFinalC = new object[] { new object(), default(int), String.Empty };

            // Act
            IMethodInvoker <MethodInvokerFactoryTests> invoker =
                MethodInvokerFactory.Create <MethodInvokerFactoryTests>(method);

            // Assert
            Assert.NotNull(invoker);
            bool        callbackCalled = false;
            ByRefAction callback       = delegate(ref int a, ref string b, ref object[] c)
            {
                callbackCalled = true;
                Assert.Equal(expectedInitialA, a);
                Assert.Same(expectedInitialB, b);
                Assert.Same(expectedInitialC, c);
                a = expectedFinalA;
                b = expectedFinalB;
                c = expectedFinalC;
            };
            MethodInvokerFactoryTests instance = GetInstance(isInstance);

            object[] arguments = new object[] { expectedInitialA, expectedInitialB, expectedInitialC, callback };
            invoker.InvokeAsync(instance, arguments).GetAwaiter().GetResult();
            Assert.True(callbackCalled);
            Assert.Equal(expectedFinalA, arguments[0]);
            Assert.Same(expectedFinalB, arguments[1]);
            Assert.Same(expectedFinalC, arguments[2]);
        }
コード例 #16
0
        public void CreateTest()
        {
            MethodInvokerFactory target = new MethodInvokerFactory();  
            MethodInfo[] myMethodInfo;
            Type myType = typeof(MyClass);
            // Get the type and fields of FieldInfoClass.
            myMethodInfo = myType.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance
                | BindingFlags.Public);

            MethodInfo key = myMethodInfo[0];
 
            IMethodInvoker actual;
            actual = target.Create(key);  
            Assert.IsNotNull(actual);
        }
コード例 #17
0
 public void MethodInvokerFactoryConstructorTest()
 {
     MethodInvokerFactory target = new MethodInvokerFactory();
     Assert.IsNotNull(target);
 }
コード例 #18
0
        private void CreateCommandsFromAssemblies(int prefixParameters)
        {
            var methods = ScanMethods();

            foreach (var(method, commandInfo) in methods)
            {
                // Determine command name.
                var name = commandInfo.Name ?? GetCommandName(method);
                if (name == null)
                {
                    continue;
                }

                // Validate acceptable return type.
                if (method.ReturnType != typeof(bool) &&
                    method.ReturnType != typeof(int) &&
                    method.ReturnType != typeof(void))
                {
                    continue;
                }

                var methodParameters = method.GetParameters();
                // Determine command parameter types.
                if (!TryCollectParameters(methodParameters, prefixParameters, out var parameters))
                {
                    continue;
                }

                var info = new CommandInfo(name, parameters);

                var argsPtr          = 0; // The current pointer in the event arguments array.
                var parameterSources = methodParameters
                                       .Select(inf => new MethodParameterSource(inf))
                                       .ToArray();

                // Determine the source of each parameter.
                for (var i = 0; i < parameterSources.Length; i++)
                {
                    var source = parameterSources[i];
                    var type   = source.Info.ParameterType;

                    if (typeof(Component).IsAssignableFrom(type))
                    {
                        // Components are provided by the entity in the arguments array of the event.
                        source.ParameterIndex = argsPtr++;
                        source.IsComponent    = true;
                    }
                    else if (info.Parameters.FirstOrDefault(p => p.Index == i) != null)
                    {
                        // Default types are passed straight trough.
                        source.ParameterIndex = argsPtr++;
                    }
                    else
                    {
                        // Other types are provided trough Dependency Injection.
                        source.IsService = true;
                    }
                }

                var data = new CommandData
                {
                    Arguments  = new object[info.Parameters.Length + prefixParameters],
                    Info       = info,
                    Invoke     = MethodInvokerFactory.Compile(method, parameterSources, false),
                    SystemType = method.DeclaringType
                };

                if (!_commands.TryGetValue(info.Name, out var lst))
                {
                    lst = _commands[info.Name] = new List <CommandData>();
                }

                lst.Add(data);
            }
        }