Отражение против MEF или оба - PullRequest
0 голосов
/ 11 октября 2019

Я создаю приложение 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}" });
        }
    }
...