How to Build Expression Tree for Invoke Method from Generic Interface - c#

I'm sorry to ask, how can i invoke method using other that method.Invoke, because some article said, method.Invoke has slower performance.
Actually i'm using .NET Core 3.1.
Example, i have a structure code something like this.
public class Message { }
public class MyMessageType : Message { }
public class MyMessageResult
{
public bool Status { get; set; }
public DateTime Date => DateTime.Now;
}
public interface IEncapsulatedMessageHandlerV2<T, TResult> where T : class
{
Task<TResult> HandleMessageResultAsync(T message);
}
public abstract class EncasulatedMessageHandlerV2<T, TResult> : IEncapsulatedMessageHandlerV2<T, TResult> where T : Message
{
public abstract Task<TResult> HandleMessageResultExecAsync(T message);
async Task<TResult> IEncapsulatedMessageHandlerV2<T, TResult>.HandleMessageResultAsync(T message)
{
var msg = message as T;
if (msg != null)
return await HandleMessageResultExecAsync(msg);
return default;
}
}
public class HandlerV2 : EncasulatedMessageHandlerV2<MyMessageType, MyMessageResult>
{
public override Task<MyMessageResult> HandleMessageResultExecAsync(MyMessageType message)
{
Console.WriteLine("Yo Async!");
return Task.FromResult(new MyMessageResult
{
Status = true
});
}
}
And i can successfully call using method.Invoke
static TResponse UsingMethodInvoke<TResponse>()
{
// Assume, i was build this using MakeGenericMethod
var type = typeof(IEncapsulatedMessageHandlerV2<MyMessageType, MyMessageResult>);
var typeActivator = typeof(HandlerV2);
var instance = Activator.CreateInstance(typeActivator);
var method = type.GetMethod("HandleMessageResultAsync");
var tsk = (Task<TResponse>)method.Invoke(instance, new[] { new MyMessageType() });
var result = tsk.GetAwaiter().GetResult();
return result;
}
And i try to using Dynamic too, unfortunately they can't calling through abstract HandleMessageResultAsync instead only through implemented class HandleMessageResultExecAsync
static TResponse UsingDynamicInvoke<TResponse>()
{
// Assume, i was build this using MakeGenericMethod
var typeActivator = typeof(HandlerV2);
var instance = Activator.CreateInstance(typeActivator);
var tsk = (Task<TResponse>)((dynamic)instance).HandleMessageResultExecAsync(new MyMessageType());
var result = tsk.GetAwaiter().GetResult();
return result;
}
And i was follow to with stackoverflow Speeding up Reflection Invoke C#/.NET, and i get stuck
static void ActivatorMyMessageResultAsnc()
{
var type = typeof(HandlerV2);
var instance = Activator.CreateInstance(type);
var method = type.GetMethod("HandleMessageResultAsync", BindingFlags.Instance | BindingFlags.Public);
var originalType = type;
// Loop until we hit the type we want.
while (!(type.IsGenericType) || type.GetGenericTypeDefinition() != typeof(EncasulatedMessageHandlerV2<,>))
{
type = type.BaseType;
if (type == null)
throw new ArgumentOutOfRangeException("type");
}
var messageType = type.GetGenericArguments()[0]; // MyMessageType
// Use expression to create a method we can.
var instExpr = Expression.Parameter(typeof(object), "instance");
var paramExpr = Expression.Parameter(typeof(Message), "message");
// (Handler)instance;
var instCastExpr = Expression.Convert(instExpr, originalType);
// (MyMessageType)message
var castExpr = Expression.Convert(paramExpr, messageType);
// ((Handler)inst).HandleMessage((MyMessageType)message)
var invokeExpr = Expression.Call(instCastExpr, method, castExpr); // <--- this give me error
// i'm stuck, i don't know what should i do next
////// Assume this is build from MakeGeneric too
////var delType = typeof(Func<object, Message, Task<MessageResult>>);
//var lambda = Expression.Lambda<Func<object, Message, Task<object>>>(invokeExpr, instExpr, paramExpr);
//var compiled = lambda.Compile();
//Func<Message, Task<object>> hook = x => compiled(instance, x);
Or, is there any other ways to Invoke method by dynamicaly, which is faster that method.Invoke
Thanks in advance,
PS: Sorry for my Bad English

I had a similar problem I was trying to solve a while back. I dug into the Net Core codebase and found a class which is really helpful for invoking methods at runtime without being strongly typed.
https://github.com/dotnet/extensions/blob/ff87989d893b000aac1bfef0157c92be1f04f714/shared/Microsoft.Extensions.ObjectMethodExecutor.Sources/ObjectMethodExecutor.cs
ObjectMethodExecutor lets you call a method on an object using its name. An example of usage is:
var methodInfo = [myInterface].GetMethod("[method-you-want-call]");
var classTypeInfo = [myClass].GetTypeInfo();
var executor = ObjectMethodExecutor.Create(methodInfo, classTypeInfo);
await executor.ExecuteAsync(handler, new[] { [data-you-want-to-pass-to-your-object] });
Its used extensively in the SignalR codebase for matching SignalR messages to the internal methods on a hub. Its heavily optimised and has the added benefit of allowing async methods to be called too

Related

Returning a generic type without T at compile time

I have a list of generics defined like so:
class Registrations
{
private readonly List<MetaRegistration> _registrations = new List<MetaRegistration>();
private abstract class MetaRegistration
{
}
private class Registration<T> : MetaRegistration
{
public async Task<T> Resolve(string value)
{
return await ...
}
}
}
And I'd like to run a method on one of the Registration<T> instances.
I can easily do it like this if I know the type at compile time:
public async Task<T> Resolve<T>(string value)
{
var registration = _registrations.Cast<Registration<T>>()
.First(r => r.GetType().GenericTypeArguments[0] == typeof(T));
var model = await registration.Resolve(value);
return model;
}
But how would I go about this without when I don't know T?
Right now, this is how I've come around the problem using reflection, where I know the Type, but only during runtime:
public async Task<object?> Resolve(Type type, string value)
{
foreach (var metaRegistration in _registrations)
{
Type t = metaRegistration.GetType();
if (!t.IsGenericType || t.GetGenericTypeDefinition() != typeof(Registration<>) ||
t.GenericTypeArguments[0] != type) continue;
var methodInfo = metaRegistration.GetType().GetMethod("Resolve");
var task = (Task) methodInfo?.Invoke(metaRegistration, new object?[] {value})!;
await task;
return task.GetType().GetProperty("Result")?.GetValue(task);
}
return null;
}
However, I would prefer to avoid reflection together, and this feels like I'm doing something incorrectly.
Is there any other way to go about this?

Get name of generic method inside a proxy class

I would like to create a proxy class that will be able to retrieve the name of a method given in argument, and an instance of a paramater with generic completion (aka I don't want nameof() or magic strings).
For example, I would like to be able to do something like
public interface ITestInterface
{
void TestMethod(Param myParam)
}
var proxy = new Proxy<ITestInterface>();
var param = new Param();
proxy.WriteName(x => ITestInterface.TestMethod(param));
and the proxy class be able to retrive the name of the method and do a tostring on the instance of the parameter :
public class Proxy<T>
{
public void WriteName(Something something)
{
Console.WriteLine(something.MethodName); // write "TestMethod"
Console.WriteLine(something.Parameter.ToString()); // use the tostring of the instance object
}
}
Thanks for your help
I would say it would not be easy to support all possible scenarios but for what you have described in the question you can try using expression trees:
public class Proxy<T>
{
public void WriteName(Expression<Action<T>> something)
{
// TODO: add correct handling for not supported operations
if (something.Body is MethodCallExpression mc)
{
Console.WriteLine(mc.Method.Name);
foreach (var arg in mc.Arguments)
{
if (arg is MemberExpression me && me.Expression is ConstantExpression cnst)
{
var val = me.Member.MemberType switch
{
MemberTypes.Field => ((FieldInfo)me.Member).GetValue(cnst.Value),
MemberTypes.Property => ((PropertyInfo)me.Member).GetValue(cnst.Value),
_ => null
};
Console.WriteLine(val);
}
}
}
}
}
And usage:
var proxy = new Proxy<ITestInterface>();
var param = new Param();
proxy.WriteName(t => t.TestMethod(param)); // actually many more can be passed here
If I understand correctly you can try this:
public class Proxy<T>
{
public void WriteName(Expression<Action> action)
{
var methodCallExp = (MethodCallExpression)action.Body;
Console.WriteLine(methodCallExp.Arguments.First().ToString());
Console.WriteLine(methodCallExp.Method.Name);
}
}
and call proxy class like this:
var proxy = new Proxy<ITestInterface>();
proxy.WriteName(() => new ConcreteTestInterface().TestMethod(param));

Is there any way to add open generic formatters to ASP.Net Core 2.0 via ConfigureServices in Startup

As per the title, I would like to be able to add open generic InputFormatter and OutputFormatter instances as part of ConfigureServices in Startup.cs, similarly to how it is possible to add open generic services.
What I would like would look somehitng like this:
services.AddMvc(options =>
{
options.InputFormatters.Add(new ProtobufInputFormatter<>());
options.OutputFormatters.Add(new ProtobufOutputFormatter<>());
options.FormatterMappings.SetMediaTypeMappingForFormat("protobuf", MediaTypeHeaderValue.Parse("application/x-protobuf"));
});
Is this possible in any way?
Edit:
Example of currently implemented ProtobufOutputFormatter
public class ProtobufInputFormatter : InputFormatter
{
static MediaTypeHeaderValue protoMediaType = MediaTypeHeaderValue.Parse("application/x-protobuf");
public override bool CanRead(InputFormatterContext context)
{
var request = context.HttpContext.Request;
MediaTypeHeaderValue requestContentType = null;
MediaTypeHeaderValue.TryParse(request.ContentType, out requestContentType);
if (requestContentType == null)
{
return false;
}
return requestContentType.IsSubsetOf(protoMediaType);
}
public override Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context)
{
try
{
var request = context.HttpContext.Request;
var obj = (IMessage)Activator.CreateInstance(context.ModelType);
obj.MergeFrom(request.Body);
return InputFormatterResult.SuccessAsync(obj);
}
catch (Exception ex)
{
Console.WriteLine("Exception: " + ex);
return InputFormatterResult.FailureAsync();
}
}
}
The issue is that using reflection is not as performant as if I were able to use the generic Protobuf deserialiser, eg something like this:
public class ProtobufInputFormatter<T> : InputFormatter where T : IMessage<T>, new()
{
static MediaTypeHeaderValue protoMediaType = MediaTypeHeaderValue.Parse("application/x-protobuf");
public override bool CanRead(InputFormatterContext context)
{
var request = context.HttpContext.Request;
MediaTypeHeaderValue requestContentType = null;
MediaTypeHeaderValue.TryParse(request.ContentType, out requestContentType);
if (requestContentType == null)
{
return false;
}
return requestContentType.IsSubsetOf(protoMediaType);
}
public override Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context)
{
try
{
var request = context.HttpContext.Request;
var serialiser = new ProtobufSerialiser<T>();
var obj = serialiser.Deserialise(request.Body);
return InputFormatterResult.SuccessAsync(obj);
}
catch (Exception ex)
{
Console.WriteLine("Exception: " + ex);
return InputFormatterResult.FailureAsync();
}
}
The ProtobufSerialiser is a wrapper around Google.Protobuf we have (implemented to work with a Buffer Pool for performance reasons which is subverted by the need for Activator.CreateInstance as seen in the actual implemented and working non-generic example above.)
The T would come from the endpoint.
I don't think it's possible, it's just not designed to provide current model type as generic type argument to formatter (in case formatter is generic).
If you measured that reflection (by using non-generic version) is slowing you down, I'd suggest to use compiled expression trees instead, and cache them. For example in this case you need this:
var serialiser = new ProtobufSerialiser<T>();
var obj = serialiser.Deserialise(request.Body);
Which can be represented as expression:
Expression<Func<Stream, object>> body => new ProtobufSerializer<T>().Deserialize(body);
Assuming you ProtobufSerializer<T> is something like this:
class ProtobufSerializer<T> where T: new() {
public T Deserialize(Stream body) {
...
}
}
You can construct expression above at runtime like this:
public static class SerializersCache {
private static readonly ConcurrentDictionary<Type, Func<Stream, object>> _cache = new ConcurrentDictionary<Type, Func<Stream, object>>();
public static object Deserialize(Type type, Stream body) {
var handler = _cache.GetOrAdd(type, (key) => {
var arg = Expression.Parameter(typeof(Stream), "body");
var genericSerializer = typeof(ProtobufSerializer<>).MakeGenericType(key);
// new ProtobufSerializer<T>();
var instance = Expression.New(genericSerializer.GetConstructor(new Type[0]));
// new ProtobufSerializer<T>().Deserialize(body);
var call = Expression.Call(instance, "Deserialize", new Type[0], arg);
// body => new ProtobufSerializer<T>().Deserialize(body);
return Expression.Lambda<Func<Stream, object>>(call, arg).Compile();
});
return handler(body);
}
}
And your (non-generic) input formatter becomes:
var request = context.HttpContext.Request;
var obj = SerializersCache.Deserialize(context.ModelType, request.Body);

Create Expression for new Action<T> where T is unknown at compile time

Edit2: removed a load of gubbins + bounty.
I have deconstructed an expression for a message bus in the hope of reconstructing it and invoking it in a slightly different manner. The serialization and deserialization is successful and I am able to create instances of most of what I need.
//Deconstruct
Expression<Func<T, Task>> expression
proxy => proxy.serviceMethod(arg);
I need to create the syntax below. T is an interface to a WCF service. This expression will be passed to a service invoker where it's internal ChannelFactory will pass it into this method.
//Reconstruct this as expression so I can pass it as a parameter
var myAction = new Action<T>(proxy => {
proxy.serviceMethod((SomeType)SomeParameter));
});
// to pass to this method
serviceInvokerTMethod.Invoke(serviceInvokerTInstance, new object[] { myAction });
What I have:
//I think i'm nearly there I can create the inner call and assign
//the correct parameter, but I can't seem to figure out how to wrap it in an
// new Action<serviceT> { my other expressions... }
// Types
var serviceT = Type.GetType(workOutMessage.interfaceType);
var actionT = typeof(Action<>).MakeGenericType(serviceT);
var envelopeT = Type.GetType(workOutMessage.methodArgTypes[0]);
// ServiceInvoker<T> Instantiation - Works
var serviceInvokerT = typeof(HubServiceInvoker<>).MakeGenericType(serviceT);
var serviceInvokerTMethod = serviceInvokerT.GetMethod("InvokeService");
var serviceInvokerTInstance = Activator.CreateInstance(serviceInvokerT, client.Id, "password", clientCert, serviceCert);
// Expression Type Params
var serviceTParam = Expression.Parameter(serviceT, "proxy");
var envelopeParam = Expression.Parameter(envelopeT, "envelope");
var envAssign = Expression.Assign(envelopeParam, Expression.Constant(workOutMessage.methodArgs[0]));
var methodCall = Expression.Call(serviceTParam, serviceT.GetMethod(workOutMessage.methodName), envelopeParam);
// var lambda = ...
// make new Action<serviceT> myAction = { proxy => proxy.someMethod(someParameter); };
serviceInvokerTMethod.Invoke(serviceInvokerTInstance, new object[] { lambda.Compile() });
Edit: The Service Invoker Method I pass this into to, to try and give the problem better context.
public void InvokeService(Action<T> handler)
{
T proxy = channelFactory.CreateChannel();
((IClientChannel)proxy).Faulted += ChannelFaulted;
ICommunicationObject obj2 = (ICommunicationObject)proxy;
try
{
using (new OperationContextScope((IContextChannel)proxy))
{
handler.Invoke(proxy);
}
}
finally
{
try
{
if (obj2.State != CommunicationState.Faulted)
{
obj2.Close();
}
}
catch
{
obj2.Abort();
}
}
}
Here is a full piece of code, in which I assume you only need a Func, not an Action.
using System;
using System.Linq.Expressions;
using System.Threading.Tasks;
namespace HelloWorld
{
public class Service1
{
public Task ServiceMethod(string something)
{
return Task.Factory.StartNew(() => Console.WriteLine(something));
}
}
public class HubServiceInvoker<T> where T : new()
{
T t;
public HubServiceInvoker(string id, string password)
{
t = new T();
}
public void InvokeService(Func<T, Task> serviceInvoker)
{
Task task = serviceInvoker(t);
}
public static Func<T, Task> CompileInvoker(Expression expression, ParameterExpression serviceTParam)
{
Expression<Func<T, Task>> lambda = Expression.Lambda<Func<T, Task>>(expression, serviceTParam);
return lambda.Compile();
}
}
public class WorkOutMessage
{
public string interfaceType { get; set; }
public string[] methodArgTypes { get; set; }
public object[] methodArgs { get; set; }
public string methodName { get; set; }
}
static class Program
{
static void Main(string[] args)
{
WorkOutMessage workOutMessage = new WorkOutMessage()
{
interfaceType = "HelloWorld.Service1",
methodArgTypes = new string[] { "System.String" },
methodArgs = new object[] { "yeah it works!" },
methodName = "ServiceMethod"
};
InvokeService(workOutMessage);
Console.Read();
}
static void InvokeService(WorkOutMessage workOutMessage)
{
// Types
var serviceT = Type.GetType(workOutMessage.interfaceType);
// ServiceInvoker<T> Instantiation - Works
var serviceInvokerT = typeof(HubServiceInvoker<>).MakeGenericType(serviceT);
var serviceInvokerTMethod = serviceInvokerT.GetMethod("InvokeService");
var serviceCompileInvokerTMethod = serviceInvokerT.GetMethod("CompileInvoker");
var serviceInvokerTInstance = Activator.CreateInstance(serviceInvokerT, "id", "password");
// Expression Type Params
var serviceTParam = Expression.Parameter(serviceT, "proxy");
var methodCall = Expression.Call(serviceTParam, serviceT.GetMethod(workOutMessage.methodName), Expression.Constant(workOutMessage.methodArgs[0]));
serviceInvokerTMethod.Invoke(serviceInvokerTInstance, new object[] {
serviceCompileInvokerTMethod.Invoke(serviceInvokerTInstance, new object[] { methodCall, serviceTParam })
});
}
}
}
It was a little bit hard to understand what exactly is going on.
Perhaps, this will help you a little bit further:
// Helper.cs
public static Action<TType> Wrap<TType>(Delegate test)
{
return ret => test.DynamicInvoke();
}
var meth = typeof(Helper).GetMethod("Wrap");
var gmeth = meth.MakeGenericMethod(new[] { serviceT });
var genericAction = gmeth.Invoke(null, new object[] {
Expression.Lambda(methodCall).Compile(); });
Thanks to the hints from #Romain Hautefeuille, the key was to use my generic ServiceInvoker class to help me create the action that I needed without the need of using Expressions (woohoo).
// Execute Interface method from interface, methodName and methodArgs from message queue
var serviceT = Type.GetType(workOutMessage.interfaceType);
var serviceInvokerT = typeof(HubServiceInvoker<>).MakeGenericType(serviceT);
var serviceInvokerTMethod = serviceInvokerT.GetMethod("InvokeService");
var serviceInvokerCompileTMethod = serviceInvokerT.GetMethod("CompileServiceMethod");
var serviceInvokerTInstance = Activator.CreateInstance(serviceInvokerT, client.Id,
"password", clientCert, serviceCert);
// Works! and a lot simpler
serviceInvokerTMethod.Invoke(serviceInvokerTInstance, new object[] {
workOutMessage.correlationId,
serviceInvokerCompileTMethod.Invoke(serviceInvokerTInstance, new object[] {
workOutMessage.methodName,
workOutMessage.methodArgs })
});
And Finally the new method in the ServiceInvoker class (I wanted to avoid reflection in this class - for no particular reason - but it doesn't affect calling it normally).
public Action<T> CompileServiceMethod(string methodName, object[] methodArguments)
{
return new Action<T>(proxy =>
{
typeof(T).GetMethod(methodName).Invoke(proxy, methodArguments);
});
}

How to wrap a static class in a non-static instance object (dynamically)

I have an interesting problem. I need to wrap static classes dynamically. I.e. return a non-static instance to my callers. e.g.:
public object CreateInstance(string className) {
Type t = assembly.GetType(className);
if (IsStatic(t)) {
return CreateStaticWrapper(t);
} else {
return Activator.CreateInstance(t);
}
}
So what I need is pointers as to how to implement CreateStaticWrapper.
Note: I cannot use Dynamic objects unfortunately.
So what are my options? I'm not that keen on learning IL generation? If IL generation (Reflection.Emit, or is there other ways now?) is the way to go does anyone have pointers there?
Edit: It's important to note that I can return a Dictionary of Delegates. So I could use Delegate.CreateDelegate for this but I can't seem to work out how to handle overloaded methods and Generic methods.
Edit2: Another option would be to inject an empty constructor into the type using Emit, again any pointers? Is this even possible on a type marked as static? Does the static keyword make it into the IL?
Edit3: For a bit of context, I'm passing this to a javascript environment see: my project. So I would like to be able to (in JavaScript):
var fileHelper = .create('System.IO.File');
if (fileHelper.Exists(fileName)) { fileHelper.Delete(fileName); }
Thanks All.
Try creating a wrapper class which inherits from System.Dynamic.DynamicObject. In the wrapper class, use reflection to call the methods of the static class.
You need something like this:
public class StaticWrapper<T> : System.Dynamic.DynamicObject
{
private static readonly Type t = typeof(T);
public static int MyProperty { get; set; }
public override bool TryInvokeMember(System.Dynamic.InvokeMemberBinder binder, object[] args, out object result)
{
try
{
result = t.InvokeMember(binder.Name, BindingFlags.Static | BindingFlags.Public, null, null, args);
return true;
}
catch
{
result = null;
return false;
}
}
public override bool TryGetMember(System.Dynamic.GetMemberBinder binder, out object result)
{
try
{
var p = t.GetProperty(binder.Name);
if (p != null)
result = p.GetValue(null, null);
else
{
var f = t.GetField(binder.Name);
if (f != null) result = f.GetValue(null);
else { result = null; return false; }
}
return true;
}
catch
{
result = null;
return false;
}
}
public override bool TrySetMember(System.Dynamic.SetMemberBinder binder, object value)
{
try
{
var p = t.GetProperty(binder.Name);
if (p != null)
p.SetValue(null, value, null);
else
{
var f = t.GetField(binder.Name);
if (f != null) f.SetValue(null, value);
else return false;
}
return true;
}
catch (SystemException)
{
return false;
}
}
}
Hope it works.
I'd say go for IL generation. Creating a proxy is a pretty simple scenario. I actually wrote a blog post about it: einarwh.posterous.com/patching-polymorphic-pain-at-runtime. The scenario is different, but the solution almost identical.
You can basically do exactly as in the blog post, except you don't need to load the 'this' reference onto the stack (since you're doing static method calls).
Ok, well the solution I've come up with is as follows and was found reading through and studying Einar's blog post which he posted as a comment above. Thanks Einar.
But I thought I'd post my full code solution here in case it may help someone in the future:
using System;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
namespace js.net.jish.Command
{
public class StaticTypeWrapper
{
private readonly Type staticType;
public StaticTypeWrapper(Type staticType)
{
this.staticType = staticType;
}
public object CreateWrapper()
{
string ns = staticType.Assembly.FullName;
ModuleBuilder moduleBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(new AssemblyName(ns), AssemblyBuilderAccess.Run).DefineDynamicModule(ns);
TypeBuilder wrapperBuilder = moduleBuilder.DefineType(staticType.FullName, TypeAttributes.Public, null, new Type[0]);
foreach (MethodInfo method in staticType.GetMethods().Where(mi => !mi.Name.Equals("GetType")))
{
CreateProxyMethod(wrapperBuilder, method);
}
Type wrapperType = wrapperBuilder.CreateType();
object instance = Activator.CreateInstance(wrapperType);
return instance;
}
private void CreateProxyMethod(TypeBuilder wrapperBuilder, MethodInfo method)
{
var parameters = method.GetParameters();
var methodBuilder = wrapperBuilder.DefineMethod(method.Name, MethodAttributes.Public | MethodAttributes.Virtual, method.ReturnType, parameters.Select(p => p.ParameterType).ToArray());
var gen = methodBuilder.GetILGenerator();
for (int i = 1; i < parameters.Length + 1; i++)
{
gen.Emit(OpCodes.Ldarg, i);
}
gen.Emit(OpCodes.Call, method);
gen.Emit(OpCodes.Ret);
}
}
}
So, say that we play around with the "Delegate.CreateDelegate" way. And let's see if we can get more details about your other issues after that... Let's start with:
public static object Generate(Type t)
{
if(IsStatic(t))
{
var dictionary = new Dictionary<string, Delegate>();
foreach (var methodInfo in t.GetMethods())
{
var d = Delegate.CreateDelegate(t, methodInfo);
dictionary[methodInfo.Name] = d;
}
return dictionary;
}
return Activator.CreateInstance(t);
}
Static classes are 'sealed' and can thus not be inherited. So I don't see what you mean by 'overloaded'. For generic methods, we need to invoke the methodInfo.MakeGenericMethod(...) before adding it to our dictionary. But then you would need to know the type beforehand, which I guess you don't... Alternatively, you can do something like:
...
if (methodInfo.IsGenericMethod)
{
d = new Func<MethodInfo, Type[], Delegate>(
(method, types) =>
Delegate.CreateDelegate(
method.DeclaringType, method.MakeGenericMethod(types)));
}
dictionary[methodInfo.Name] = d;
...
That would give you a delegate that would take a type array (the generic type parameters), and produce a working delegate from that.

Categories