Created
August 30, 2019 17:35
-
-
Save scottoffen/6cc89b4b64740fa9e9f82e3112396510 to your computer and use it in GitHub Desktop.
Make delegates from methods
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Reflection; | |
using System.Linq; | |
namespace DelegateTesting | |
{ | |
public class Program | |
{ | |
public static void Main(string[] args) | |
{ | |
var myClassList = GenerateList(10); | |
var actions = MethodDelegateCache<MyClass> | |
.CandidateMethods | |
.Select(_ => MethodDelegateCache<MyClass>.GetDelegateForMethod(_)) | |
.ToList(); | |
foreach (var obj in myClassList) | |
{ | |
foreach (var action in actions) | |
{ | |
action(obj, 1); | |
} | |
} | |
var method = MethodDelegateCache<MyOtherClass>.GetDelegateForMethod("Eligible"); | |
foreach (var name in new List<string> { "Herman", "Fausta", "Cleo" }) | |
{ | |
var other = new MyOtherClass(name); | |
method(other, 999); | |
} | |
} | |
public static List<MyClass> GenerateList(int count) | |
{ | |
var myClassList = new List<MyClass>(); | |
for (var i = 0; i < count; i++) | |
{ | |
myClassList.Add(new MyClass { Number = i }); | |
} | |
return myClassList; | |
} | |
} | |
public class MyClass | |
{ | |
public int Number { get; set; } | |
public void DoSomething(int value) | |
{ | |
Console.WriteLine($"{value} Do Something"); | |
} | |
public void DoNothing(int value) | |
{ | |
Console.WriteLine($"{value} Do Nothing"); | |
} | |
public void DoSmile(int value) | |
{ | |
Console.WriteLine($"{value} Do Smile"); | |
} | |
public void NotMe1(int value, int other) | |
{ | |
} | |
public void NotMe2(string value) | |
{ | |
} | |
public int NotMe3(int value) | |
{ | |
return value; | |
} | |
} | |
public class MyOtherClass | |
{ | |
private string _name; | |
public MyOtherClass(string name) | |
{ | |
_name = name; | |
} | |
public void Eligible(int value) | |
{ | |
Console.WriteLine($"{value} {_name} Eligible"); | |
} | |
} | |
public static class MethodDelegateCache<T> | |
{ | |
private static Dictionary<string, Action<T, int>> cache = new Dictionary<string, Action<T, int>>(); | |
private static Dictionary<string, MethodInfo> mcache = new Dictionary<string, MethodInfo>(); | |
static MethodDelegateCache() | |
{ | |
var type = typeof(T); | |
Console.WriteLine($"Type: {type.Name}"); | |
var methods = typeof(T).GetMethods(BindingFlags.Public|BindingFlags.Instance) | |
.Where(m => | |
{ | |
if (m.IsSpecialName) return false; | |
var args = m.GetParameters(); | |
var retval = m.ReturnType; | |
return (args.Length == 1 && args[0].ParameterType == typeof(int) && retval == typeof(void)); | |
}).ToList(); | |
Console.WriteLine($"Methods: {methods.Count}"); | |
foreach (var method in methods) | |
{ | |
Console.WriteLine($" └── {method.Name}"); | |
mcache.Add(method.Name, method); | |
} | |
Console.WriteLine("Done getting methods"); | |
} | |
public static Action<T, int> GetDelegateForMethod(string name) | |
{ | |
if (mcache.ContainsKey(name)) | |
{ | |
if (!cache.ContainsKey(name)) | |
{ | |
var action = (Action<T, int>)Delegate.CreateDelegate(typeof(Action<T, int>), null, mcache[name]); | |
cache.Add(name, action); | |
} | |
return cache[name]; | |
} | |
throw new NotImplementedException($"{typeof(T).Name} does not contain a valid definition for method {name}"); | |
} | |
public static Action<T, int> GetDelegateForMethod(MethodInfo info) | |
{ | |
return GetDelegateForMethod(info.Name); | |
} | |
public static List<MethodInfo> CandidateMethods => mcache.Values.ToList(); | |
public static List<string> CandidateMethodNames => mcache.Keys.ToList(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment