unity delegados crear c# .net reflection delegates methodinfo

unity - crear delegados en c#



¿Cómo crear un delegado desde un MethodInfo cuando la firma del método no puede conocerse de antemano? (2)

Necesito un método que tome una instancia de MethodInfo represente un método estático no genérico con firma arbitraria y devuelve un delegado vinculado a ese método que luego podría invocarse mediante el método Delegate.DynamicInvoke . Mi primer intento ingenuo se veía así:

using System; using System.Reflection; class Program { static void Main() { var method = CreateDelegate(typeof (Console).GetMethod("WriteLine", new[] {typeof (string)})); method.DynamicInvoke("Hello world"); } static Delegate CreateDelegate(MethodInfo method) { if (method == null) { throw new ArgumentNullException("method"); } if (!method.IsStatic) { throw new ArgumentNullException("method", "The provided method is not static."); } if (method.ContainsGenericParameters) { throw new ArgumentException("The provided method contains unassigned generic type parameters."); } return method.CreateDelegate(typeof(Delegate)); // This does not work: System.ArgumentException: Type must derive from Delegate. } }

MethodInfo.CreateDelegate que el método MethodInfo.CreateDelegate pudiera encontrar el tipo de delegado correcto. Bueno, obviamente no puede. Entonces, ¿cómo creo una instancia de System.Type represente un delegado con una firma que coincida con la instancia de MethodInfo proporcionada?


Es posible que desee probar System.LinQ.Expressions

... using System.Linq.Expressions; ... static Delegate CreateMethod(MethodInfo method) { if (method == null) { throw new ArgumentNullException("method"); } if (!method.IsStatic) { throw new ArgumentException("The provided method must be static.", "method"); } if (method.IsGenericMethod) { throw new ArgumentException("The provided method must not be generic.", "method"); } var parameters = method.GetParameters() .Select(p => Expression.Parameter(p.ParameterType, p.Name)) .ToArray(); var call = Expression.Call(null, method, parameters); return Expression.Lambda(call, parameters).Compile(); }

y úsala luego como sigue

var method = CreateMethod(typeof (Console).GetMethod("WriteLine", new[] {typeof (string)})); method.DynamicInvoke("Test Test");


Puede usar el método System.Linq.Expressions.Expression.GetDelegateType :

using System; using System.Linq; using System.Linq.Expressions; using System.Reflection; class Program { static void Main() { var writeLine = CreateDelegate(typeof(Console).GetMethod("WriteLine", new[] { typeof(string) })); writeLine.DynamicInvoke("Hello world"); var readLine = CreateDelegate(typeof(Console).GetMethod("ReadLine", Type.EmptyTypes)); writeLine.DynamicInvoke(readLine.DynamicInvoke()); } static Delegate CreateDelegate(MethodInfo method) { if (method == null) { throw new ArgumentNullException("method"); } if (!method.IsStatic) { throw new ArgumentException("The provided method must be static.", "method"); } if (method.IsGenericMethod) { throw new ArgumentException("The provided method must not be generic.", "method"); } return method.CreateDelegate(Expression.GetDelegateType( (from parameter in method.GetParameters() select parameter.ParameterType) .Concat(new[] { method.ReturnType }) .ToArray())); } }

Probablemente haya un error de copiar y pegar en el 2do cheque para el !method.IsStatic : no debe usar ArgumentNullException allí. Y es un buen estilo proporcionar un nombre de parámetro como argumento para ArgumentException .

Utilice method.IsGenericMethod si desea rechazar todos los métodos y métodos genéricos. method.ContainsGenericParameters genéricos si desea rechazar solo los métodos genéricos que tengan parámetros de tipo no sustituidos.