Я создаю приложение CLI, которое принимает строку в качестве входных данных и вызывает определенный метод из списка плагинов. Методы, которые могут быть вызваны, могут иметь несколько, ни одного, или необязательные параметры. При использовании MEF экспорт должен иметь одинаковые сигнатуры методов. Я хочу, чтобы люди, которые будут реализовывать методы, предоставляли только необходимый код, а не занимались интеграцией.
Подход, о котором я думал, использовал как отражение, так и MEF. Вместо метаданных в качестве контракта у меня будет имя метода, параметры типа и требуемое количество параметров. Затем основное приложение вызовет метод, используя предоставленное имя функции. Мне нужно будет сначала проверить параметры в главном приложении, прежде чем вызывать какой-либо метод.
Мой вопрос: как правильно это сделать? Пожалуйста, смотрите код:
Оригинальный подход
public interface ICommand
{
(bool, IEnumerable<string>) Execute(object[] args);
}
public interface ICommandMetadata
{
string Name { get; }
Type[] ParamTypes { get; }
int RequiredParams { get; }
}
[Export(typeof(ICommand))]
[ExportMetadata("Name", "CustomImplementation")]
[ExportMetadata("ParamTypes", new Type[]{ typeof(string), typeof(double) })]
[ExportMetadata("RequiredParams", 1)]
public class CustomImplementation : ICommand
{
public (bool, IEnumerable<string>) Execute(object[] args)
{
var result = MainImplementation(args[0].ToString(), (double)args[1]);
return (true, new List<string> { $"Result: {result}" });
}
private int MainImplementation(string strA, double douB = 5)
{
return strA.Length + (int)douB;
}
}
Если оба подхода Reflection + MEF, я думаю вот так:
public interface ICommand
{
string FunctionName { get; }
Type[] ParamTypes { get; }
int RequiredParams { get; }
}
[Export(typeof(ICommand))]
public class CustomImplementation : ICommand
{
public string FunctionName { get { return "MainImplementation"; } }
public Type[] ParamTypes { get { return new Type[] { typeof(string), typeof(double) }; } }
public int RequiredParams { get { return 1; } }
private (bool, IEnumerable<string>) MainImplementation(string strA, double douB = 5)
{
return (true, new List<string> { $"Result: {strA.Length + (int)douB}" });
}
}