Created
July 16, 2023 09:16
-
-
Save Ilchert/f801b3d0110fd2c6f459ac93e8c07b5a to your computer and use it in GitHub Desktop.
TypeMagic.cs
This file contains hidden or 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.Linq; | |
using System.Net.Mail; | |
using System.Reflection; | |
using System.Runtime.CompilerServices; | |
using System.Text.RegularExpressions; | |
var data = new Bar(1, new Foo(2)); | |
var d = new Derive_SumEverything<Bar>(); | |
var sum = d.GetSumOfEverything(data); | |
Console.WriteLine(sum); | |
public interface ISumEverything<T> | |
{ | |
int GetSumOfEverything(T instance); | |
} | |
class Derive_SumEverything<T> : ISumEverything<T> | |
{ | |
public int GetSumOfEverything(T instance) | |
{ | |
if (instance is int i) | |
return i; | |
var sum = 0; | |
var sumMi = Mirror.GetLocalMethod(this.GetType(), nameof(GetSumOfEverything), nameof(Sum)); | |
Mirror.EachProperty(instance, sumMi, p => sum += p); | |
return sum; | |
static void Sum<U>(U propertyValue, Action<int> callback) | |
{ | |
var tcu = new Derive_SumEverything<U>(); | |
var a = tcu.GetSumOfEverything(propertyValue); | |
callback(a); | |
} | |
} | |
} | |
record Foo(int a); | |
record Bar(int a, Foo foo); | |
static class Mirror | |
{ | |
public static void EachProperty<T>(T instance, MethodInfo mi, Action<int> action) | |
{ | |
foreach (var item in typeof(T).GetProperties()) | |
{ | |
var propertyMethod = mi.MakeGenericMethod(item.PropertyType); | |
propertyMethod.Invoke(null, new object[] { item.GetValue(instance), action }); | |
} | |
} | |
public static bool IsMatchLocal(this MethodInfo localMethod, | |
string surroundingMethodName, string localMethodName) | |
=> Regex.IsMatch(localMethod.Name, | |
$@"^<{surroundingMethodName}>g__{localMethodName}\|\d+(_\d+)?"); | |
public static MethodInfo? GetLocalMethod(this Type type, | |
string surroundingMethodName, string localMethodName) | |
{ | |
var method = type.GetMethods(BindingFlags.NonPublic | BindingFlags.Static) | |
.FirstOrDefault(m => m.GetCustomAttribute<CompilerGeneratedAttribute>() != null | |
&& m.IsMatchLocal(surroundingMethodName, localMethodName)); | |
if (method is not null) return method; | |
var nestedTypes = type.GetNestedTypes(BindingFlags.NonPublic) | |
.Where(t => t.GetCustomAttribute<CompilerGeneratedAttribute>() != null); | |
foreach (var nested in nestedTypes) | |
{ | |
method = nested.GetMethods(BindingFlags.NonPublic | BindingFlags.Instance) | |
.FirstOrDefault(m => m.IsMatchLocal(surroundingMethodName, localMethodName)); | |
if (method is not null) return method; | |
} | |
return null; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment