Чтобы убедиться, что я понимаю, что вы пытаетесь сделать, если метод имеет атрибут ExecuteMe
, вы хотите вызвать метод, передав аргументы из атрибута в метод?
IЯ собираюсь предположить, что это только для экспериментов, и вы уже понимаете, что это не гарантирует, будет ли количество или тип аргументов, предоставленных для атрибута, соответствовать количеству и типу аргументов, которые требует метод.Атрибут принимает неограниченное количество объектов, а метод требует две строки.
Проблема, с которой вы сталкиваетесь, заключается в том, что вы смотрите на .GetParameters
, который ничего не говорит вам о приходящих значениях.из атрибута.Он просто описывает параметры метода.
Вам нужно получить свойство args
из атрибута и передать эти значения при вызове метода.
Только дляВ качестве иллюстрации я собираюсь использовать метод, в котором сигнатуры совпадают.
public class ClassWithMethod
{
[ExecuteMe("hello", "reflection")]
public void M3(params object[] args)
{
var strings = args.Where(arg => arg != null).Select(arg => arg.ToString());
Console.WriteLine(string.Join(", ", strings));
}
// Just to verify that we're only invoking methods with the attribute.
public void MethodWithoutAttribute() { }
}
... и в консольном приложении я просто для удобства собираюсь читать типы из исполняемой сборки.
Я переставил несколько вещей, но вы увидите, что происходитon:
static void Main(string[] args)
{
var assembly = Assembly.GetExecutingAssembly();
foreach (var type in assembly.GetTypes())
{
var methodInfos = type.GetMethods();
// looking at all the methods, not yet narrowing it down to those
// with the attribute.
foreach (var mInfo in methodInfos)
{
// We don't just want to know if it has the attribute.
// We need to get the attribute.
var executeMeParameter = mInfo.GetCustomAttribute<ExecuteMe>();
// If it's null the method doesn't have the attribute.
// Ignore this method.
if (executeMeParameter == null) continue;
// We don't need to create the instance until we know that we're going
// to invoke the method.
object act = Activator.CreateInstance(type);
// Pass the args property of the attribute (an array of objects)
// as the argument list for the method.
mInfo.Invoke(act, new object[]{executeMeParameter.args});
}
if (type.IsClass)
Console.WriteLine(type.FullName);
}
Console.ReadLine();
}
В этом случае мы просто передаем все аргументы из атрибута.Это та часть, где немного грязно.Что если args
имеет три строковых значения, а метод имеет один параметр int
?
Эта часть немного странная.Я должен был сделать это из-за ключевого слова params
.
mInfo.Invoke(act, new object[]{executeMeParameter.args});
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Другая причина, почему я предполагаю, что это только для экспериментов, состоит в том, что если вы хотите использовать атрибут, чтобы определить, какойметод для запуска и передачи жестко запрограммированных параметров (что сам по себе я не вижу), это будет намного проще:
[ExecuteMe]
public void CallM3()
{
M3("Hello", "reflection");
}
public void M3(params object[] args)
{
var strings = args.Where(arg => arg != null).Select(arg => arg.ToString());
Console.WriteLine(string.Join(", ", strings));
}
... и у атрибута нет аргументов:
public class ExecuteMe : Attribute
{
}
Разница в том, что все строго типизировано и компилируется.Вам не нужно беспокоиться о том, будут ли параметры совпадать во время выполнения.