Created
May 29, 2023 17:18
-
-
Save Const-me/5b77905635db85501352eeaa70efaf1b to your computer and use it in GitHub Desktop.
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.Linq.Expressions; | |
using System.Reflection; | |
using System.Runtime.CompilerServices; | |
static class ReflectTest | |
{ | |
/// <summary>Generic method to call</summary> | |
public static T GetValue<T>( T value ) | |
{ | |
return value; | |
} | |
/// <summary>Synchronization object to protect the cache</summary> | |
static readonly object syncRoot = new object(); | |
/// <summary>Cache compiled delegates</summary> | |
static readonly Dictionary<Type, Func<object, object>> cache = new Dictionary<Type, Func<object, object>>(); | |
/// <summary>Lookup delegate from the hash map, compile a new one if not there</summary> | |
static Func<object, object> getValueDelegate( Type t ) | |
{ | |
lock( syncRoot ) | |
{ | |
if( cache.TryGetValue( t, out Func<object, object>? pfn ) ) | |
return pfn; | |
pfn = compileDelegate( t ); | |
cache.Add( t, pfn ); | |
return pfn; | |
} | |
} | |
/// <summary>Compile generic method call into the delegate</summary> | |
[MethodImpl( MethodImplOptions.NoInlining )] | |
static Func<object, object> compileDelegate( Type t ) | |
{ | |
Type ownerType = typeof( ReflectTest ); | |
const BindingFlags bindingFlags = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; | |
MethodInfo method = ownerType.GetMethod( "GetValue", bindingFlags ) ?? | |
throw new ApplicationException( "GetValue method missing" ); | |
method = method.MakeGenericMethod( t ); | |
ParameterExpression pe = Expression.Parameter( typeof( object ), "obj" ); | |
Expression call = Expression.Call( method, Expression.Convert( pe, t ) ); | |
call = Expression.Convert( call, typeof( object ) ); | |
var lambda = Expression.Lambda<Func<object, object>>( call, pe ); | |
return lambda.Compile(); | |
} | |
/// <summary>Invoke the generic method with the correct argument type</summary> | |
static object invoke( object arg ) => | |
getValueDelegate( arg.GetType() )( arg ); | |
static void Main( string[] args ) | |
{ | |
int i = 11; | |
object result = invoke( i ); | |
Console.WriteLine( "{0}", result ); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment