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); } }
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); } } }
/// <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)); }