Пример #1
0
        /// <summary>
        /// Create a getter for a behavior parameter (possibly requiring a simulation or simulation state).
        /// </summary>
        /// <typeparam name="T">The parameter type.</typeparam>
        /// <param name="behavior">The behavior.</param>
        /// <param name="simulation">The simulation.</param>
        /// <param name="name">The parameter name.</param>
        /// <returns></returns>
        public Func <T> CreateGetter <T>(Simulation simulation, string name, IEqualityComparer <string> comparer = null)
        {
            // First find the method
            comparer = comparer ?? EqualityComparer <string> .Default;
            var method = Reflection.GetNamedMembers(this, name, comparer).FirstOrDefault(m => m is MethodInfo) as MethodInfo;

            if (method == null || method.ReturnType != typeof(T))
            {
                // Fall back to any member
                return(ParameterHelper.CreateGetter <T>(this, name, comparer));
            }
            var parameters = method.GetParameters();

            // Method: TResult Method()
            if (parameters.Length == 0)
            {
                return(Reflection.CreateGetterForMethod <T>(this, method));
            }

            // Methods with one parameter
            if (parameters.Length == 1)
            {
                // Method: <T> <Method>(<Simulation>)
                if (parameters[0].ParameterType.GetTypeInfo().IsAssignableFrom(simulation.GetType()))
                {
                    var simMethod = (Func <Simulation, T>)method.CreateDelegate(typeof(Func <Simulation, T>), this);
                    return(() => simMethod(simulation));
                }

                // Method: TResult Method(State)
                // Works for any child class of SimulationState
                var paramType = parameters[0].ParameterType;
                if (paramType.GetTypeInfo().IsSubclassOf(typeof(SimulationState)))
                {
                    // Try to find a property of the same type using reflection
                    var stateMember = simulation.GetType().GetTypeInfo()
                                      .GetProperties(BindingFlags.Public | BindingFlags.Instance)
                                      .FirstOrDefault(property => property.PropertyType == paramType);
                    if (stateMember == null)
                    {
                        return(null);
                    }

                    // Get this state
                    var state = (SimulationState)stateMember.GetValue(simulation);

                    // Create the expression
                    return(() => (T)method.Invoke(this, new[] { state }));
                }
            }

            return(null);
        }