예제 #1
0
        public static bool TryCastDelegate(this Delegate source, Type type, out Delegate result)
        {
            result = null;
            if (source == null)
            {
                return(false);
            }

            try {
                Delegate[] delegates = source.GetInvocationList();
                if (delegates.Length == 1)
                {
                    result = NETStandardShims.CreateDelegate(type, delegates[0].Target, delegates[0].GetMethodInfo());
                    return(true);
                }

                Delegate[] delegatesDest = new Delegate[delegates.Length];
                for (int i = 0; i < delegates.Length; i++)
                {
                    delegatesDest[i] = delegates[i].CastDelegate(type);
                }
                result = Delegate.Combine(delegatesDest);
                return(true);
            } catch {
                return(false);
            }
        }
예제 #2
0
        public static void ModInterop(this Type type)
        {
            if (Registered.Contains(type))
            {
                return;
            }
            Registered.Add(type);

            string prefix = type.GetTypeInfo().Assembly.GetName().Name;

            foreach (ModExportNameAttribute attrib in type.GetTypeInfo().GetCustomAttributes(typeof(ModExportNameAttribute), false))
            {
                prefix = attrib.Name;
            }

            // Collect fields and methods in the type.
            foreach (FieldInfo field in type.GetTypeInfo().GetFields(BindingFlags.Public | BindingFlags.Static))
            {
                if (!typeof(Delegate).GetTypeInfo().IsAssignableFrom(field.FieldType))
                {
                    continue;
                }
                Fields.Add(field);
            }
            foreach (MethodInfo method in type.GetTypeInfo().GetMethods(BindingFlags.Public | BindingFlags.Static))
            {
                method.RegisterModExport();
                method.RegisterModExport(prefix);
            }

            // Refresh all existing fields and methods.
            foreach (FieldInfo field in Fields)
            {
                List <MethodInfo> methods;
                if (!Methods.TryGetValue(field.GetModImportName(), out methods))
                {
                    field.SetValue(null, null);
                    continue;
                }
                // Set the field to the first matching method, or null.
                bool matched = false;
                foreach (MethodInfo method in methods)
                {
                    try {
                        field.SetValue(null, NETStandardShims.CreateDelegate(field.FieldType, null, method));
                        matched = true;
                        break;
                    } catch {
                        // Silently try the next method with the same name.
                    }
                }
                if (!matched)
                {
                    field.SetValue(null, null);
                }
            }
        }
예제 #3
0
        /// <summary>
        /// Cast a delegate from one type to another. Compatible with delegates holding an invocation list (combined delegates).
        /// </summary>
        /// <param name="source">The input delegate.</param>
        /// <param name="type">The wanted output delegate type.</param>
        /// <returns>The output delegate.</returns>
        public static Delegate CastDelegate(this Delegate source, Type type)
        {
            if (source == null)
            {
                return(null);
            }

            Delegate[] delegates = source.GetInvocationList();
            if (delegates.Length == 1)
            {
                return(NETStandardShims.CreateDelegate(type, delegates[0].Target, delegates[0].GetMethodInfo()));
            }

            Delegate[] delegatesDest = new Delegate[delegates.Length];
            for (int i = 0; i < delegates.Length; i++)
            {
                delegatesDest[i] = delegates[i].CastDelegate(type);
            }
            return(Delegate.Combine(delegatesDest));
        }