Intereting Posts
Как объединить несколько пользовательских правил StyleCop под одним узлом «Пользовательские правила» в настройках и параллелизме StyleCop Как освободить кеш изображения / память в Windows Phone 8? Не удается подключиться к FTP: (553) Имя файла не разрешено Как включить запросы кросс-генерации в ASP.NET MVC ConfigurationElementCollection с несколькими элементами ConfigurationElements различного типа Как отменить событие ComboBox SelectionChanged? Как получить разрешение экрана? Для приложения WinRT? Как изменить цвет фона столбца при использовании WPat datagrid безопасно ли NetNamedPipeBinding? Лучший способ проверить, является ли DLL-файл сборкой CLR в C # Итерация через ретранслятор Передача значений взад и вперед приложений Возможно ли вернуть страницу ASP, прежде чем продолжить работу на стороне сервера (например, протоколирование) Маршрутизация страницы в asp.net 4.0 (URL без расширения) по сравнению с PageHandlerFactory (* .aspx) Является ли плохая форма попробовать и не взаимодействовать друг с другом classы, отличные от main / form1?

Как создать делегат из MethodInfo, когда подпись метода не может быть заранее известна?

Мне нужен метод, который принимает экземпляр MethodInfo представляющий неэквивалентный статический метод с произвольной сигнатурой, и возвращает делегат, связанный с этим методом, который позже может быть вызван с использованием метода Delegate.DynamicInvoke . Моя первая наивная попытка выглядела так:

 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 может определить правильный тип делегата. Ну, очевидно, это невозможно. Итак, как мне создать экземпляр System.Type представляющий делегат с сигнатурой, соответствующей предоставленному экземпляру MethodInfo ?

Вы можете использовать метод 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())); } } 

Вероятно, ошибка копирования-вставки во второй проверке для !method.IsStatic – вы не должны использовать ArgumentNullException . И это хороший стиль для предоставления имени параметра в качестве аргумента ArgumentException .

Используйте method.IsGenericMethod если вы хотите отклонить все общие методы и метод. method.ContainsGenericParameters если вы хотите отклонить только общие методы, имеющие параметры незамкнутого типа.

Вы можете попробовать 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(); } 

и использовать его позже, как показано ниже

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