Example #1
0
        /// <summary>
        /// Initialises a new instance of the CSPlugin class
        /// </summary>
        public CSPlugin()
        {
            // Initialise
            hooks = new Dictionary <string, MethodInfo>();

            // Find all hooks
            foreach (MethodInfo method in GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance))
            {
                object[] attr = method.GetCustomAttributes(typeof(HookMethod), true);
                if (attr.Length > 0)
                {
                    HookMethod hookmethod = attr[0] as HookMethod;
                    hooks.Add(hookmethod.Name, method);
                }
            }
        }
        protected List <HookMethod> FindHooks(string name, object[] args)
        {
            HookCache hookCache;

            object[]          defaultValue;
            bool              flag;
            List <HookMethod> hookMethod = this.HooksCache.GetHookMethod(name, args, out hookCache);

            if (hookMethod != null)
            {
                return(hookMethod);
            }
            List <HookMethod> hookMethods = new List <HookMethod>();

            if (!this.Hooks.TryGetValue(name, out hookMethod))
            {
                return(hookMethods);
            }
            HookMethod hookMethod1 = null;
            HookMethod hookMethod2 = null;

            foreach (HookMethod hookMethod3 in hookMethod)
            {
                if (!hookMethod3.IsBaseHook)
                {
                    int  num   = (args != null ? (int)args.Length : 0);
                    bool flag1 = false;
                    if (num == (int)hookMethod3.Parameters.Length)
                    {
                        defaultValue = args;
                    }
                    else
                    {
                        defaultValue = ArrayPool.Get((int)hookMethod3.Parameters.Length);
                        flag1        = true;
                        if (num > 0 && defaultValue.Length != 0)
                        {
                            Array.Copy(args, defaultValue, Math.Min(num, (int)defaultValue.Length));
                        }
                        if ((int)defaultValue.Length > num)
                        {
                            for (int i = num; i < (int)defaultValue.Length; i++)
                            {
                                ParameterInfo parameters = hookMethod3.Parameters[i];
                                if (parameters.DefaultValue != null && parameters.DefaultValue != DBNull.Value)
                                {
                                    defaultValue[i] = parameters.DefaultValue;
                                }
                                else if (parameters.ParameterType.IsValueType)
                                {
                                    defaultValue[i] = Activator.CreateInstance(parameters.ParameterType);
                                }
                            }
                        }
                    }
                    if (hookMethod3.HasMatchingSignature(defaultValue, out flag))
                    {
                        if (!flag)
                        {
                            hookMethod2 = hookMethod3;
                        }
                        else
                        {
                            hookMethod1 = hookMethod3;
                            if (hookMethod1 != null)
                            {
                                hookMethods.Add(hookMethod1);
                            }
                            else if (hookMethod2 != null)
                            {
                                hookMethods.Add(hookMethod2);
                            }
                            hookCache.SetupMethods(hookMethods);
                            return(hookMethods);
                        }
                    }
                    if (!flag1)
                    {
                        continue;
                    }
                    ArrayPool.Free(defaultValue);
                }
                else
                {
                    hookMethods.Add(hookMethod3);
                }
            }
            if (hookMethod1 != null)
            {
                hookMethods.Add(hookMethod1);
            }
            else if (hookMethod2 != null)
            {
                hookMethods.Add(hookMethod2);
            }
            hookCache.SetupMethods(hookMethods);
            return(hookMethods);
        }
 protected virtual object InvokeMethod(HookMethod method, object[] args)
 {
     return(method.Method.Invoke(this, args));
 }
Example #4
0
 protected virtual object InvokeMethod(HookMethod method, object[] args) => method.Method.Invoke(this, args);
Example #5
0
        protected List <HookMethod> FindHooks(string name, object[] args)
        {
            // Get the full name of the hook `name(argument type 1, argument type 2, ..., argument type x)`
            var fullName = name;

            if (args?.Length > 0)
            {
                fullName += $"({string.Join(", ", args.Select(x => x?.GetType().ToString() ?? "null").ToArray())})";
            }

            // Check the cache if we already found a match for this hook
            if (HooksCache.ContainsKey(fullName))
            {
                return(HooksCache[fullName]);
            }

            List <HookMethod> methods;
            var matches = new List <HookMethod>();

            // Get all hook methods that could match, return an empty list if none match
            if (!Hooks.TryGetValue(name, out methods))
            {
                return(matches);
            }

            // Find matching hooks
            HookMethod exactMatch      = null;
            HookMethod overloadedMatch = null;

            foreach (var h in methods)
            {
                // A base hook should always have a matching signature either directly or through inheritance
                // and should always be called as core functionality depends on it.
                if (h.IsBaseHook)
                {
                    matches.Add(h);
                    continue;
                }

                // Check if this method matches the hook arguments passed if it isn't a base hook
                object[] hookArgs;
                var      received = args?.Length ?? 0;

                if (received != h.Parameters.Length)
                {
                    // The call argument count is different to the declared callback methods argument count
                    hookArgs = new object[h.Parameters.Length];

                    if (received > 0 && hookArgs.Length > 0)
                    {
                        // Remove any additional arguments which the callback method does not declare
                        Array.Copy(args, hookArgs, Math.Min(received, hookArgs.Length));
                    }

                    if (hookArgs.Length > received)
                    {
                        // Create additional parameters for arguments excluded in this hook call
                        for (var n = received; n < hookArgs.Length; n++)
                        {
                            var parameter = h.Parameters[n];
                            if (parameter.DefaultValue != null && parameter.DefaultValue != DBNull.Value)
                            {
                                // Use the default value that was provided by the method definition
                                hookArgs[n] = parameter.DefaultValue;
                            }
                            else if (parameter.ParameterType.IsValueType)
                            {
                                // Use the default value for value types
                                hookArgs[n] = Activator.CreateInstance(parameter.ParameterType);
                            }
                        }
                    }
                }
                else
                {
                    hookArgs = args;
                }

                bool isExactMatch;
                if (h.HasMatchingSignature(hookArgs, out isExactMatch))
                {
                    if (isExactMatch)
                    {
                        exactMatch = h;
                        break;
                    }

                    // Should we determine the level and call the closest overloaded match? Performance impact?
                    overloadedMatch = h;
                }
            }

            if (exactMatch != null)
            {
                matches.Add(exactMatch);
            }
            else
            {
                if (overloadedMatch != null)
                {
                    matches.Add(overloadedMatch);
                }
            }

            return(HooksCache[fullName] = matches);
        }
Example #6
0
 public HookMatch(HookMethod method, object[] args)
 {
     Method = method;
     Args   = args;
 }
Example #7
0
        protected List <HookMethod> FindHooks(string name, object[] args)
        {
            // Get the full name of the hook `name(argument type 1, argument type 2, ..., argument type x)`

            // Check the cache if we already found a match for this hook
            HookCache         cache;
            List <HookMethod> methods = HooksCache.GetHookMethod(name, args, out cache);

            if (methods != null)
            {
                return(methods);
            }
            List <HookMethod> matches = new List <HookMethod>();

            // Get all hook methods that could match, return an empty list if none match
            if (!Hooks.TryGetValue(name, out methods))
            {
                return(matches);
            }

            // Find matching hooks
            HookMethod exactMatch      = null;
            HookMethod overloadedMatch = null;

            foreach (HookMethod h in methods)
            {
                // A base hook should always have a matching signature either directly or through inheritance
                // and should always be called as core functionality depends on it.
                if (h.IsBaseHook)
                {
                    matches.Add(h);
                    continue;
                }

                // Check if this method matches the hook arguments passed if it isn't a base hook
                object[] hookArgs;
                int      received = args?.Length ?? 0;

                bool pooledArray = false;

                if (received != h.Parameters.Length)
                {
                    // The call argument count is different to the declared callback methods argument count
                    hookArgs    = ArrayPool.Get(h.Parameters.Length);
                    pooledArray = true;

                    if (received > 0 && hookArgs.Length > 0)
                    {
                        // Remove any additional arguments which the callback method does not declare
                        Array.Copy(args, hookArgs, Math.Min(received, hookArgs.Length));
                    }

                    if (hookArgs.Length > received)
                    {
                        // Create additional parameters for arguments excluded in this hook call
                        for (int n = received; n < hookArgs.Length; n++)
                        {
                            ParameterInfo parameter = h.Parameters[n];
                            if (parameter.DefaultValue != null && parameter.DefaultValue != DBNull.Value)
                            {
                                // Use the default value that was provided by the method definition
                                hookArgs[n] = parameter.DefaultValue;
                            }
                            else if (parameter.ParameterType.IsValueType)
                            {
                                // Use the default value for value types
                                hookArgs[n] = Activator.CreateInstance(parameter.ParameterType);
                            }
                        }
                    }
                }
                else
                {
                    hookArgs = args;
                }

                bool isExactMatch;
                if (h.HasMatchingSignature(hookArgs, out isExactMatch))
                {
                    if (isExactMatch)
                    {
                        exactMatch = h;
                        break;
                    }

                    // Should we determine the level and call the closest overloaded match? Performance impact?
                    overloadedMatch = h;
                }

                if (pooledArray)
                {
                    ArrayPool.Free(hookArgs);
                }
            }

            if (exactMatch != null)
            {
                matches.Add(exactMatch);
            }
            else
            {
                if (overloadedMatch != null)
                {
                    matches.Add(overloadedMatch);
                }
            }

            cache.SetupMethods(matches);

            return(matches);
        }