У меня есть старый код плагина C #, который был реализован строго с помощью Reflection.Исправляя некоторые проблемы совместимости C # 2.0 -> 4.0 ( «Загрузка из удаленного источника» ), я решил избавиться от старого кода отражения и заменить его интерфейсом.Интерфейс необходим, потому что теперь плагины должны быть загружены в их собственный домен приложений, а затем распределены по ним.
Я могу просмотреть источник для сотен плагинов и просто заставить их всех реализовать новый интерфейс IPlugin
спростой поиск и замена.Это прекрасно работает за исключением одного критического места. И я ищу легкий выход.
Метод RunPlugin()
может быть реализован одним из двух способов, но не обоими одновременно: либо с аргументом, либо без.Если я включу это в интерфейс, мне придется реализовать оба в каждом из плагинов.Вызывающая сторона вызывает метод с одним или без аргументов на основе , который реализован .Вызывающая сборка теперь выясняет это с помощью отражения.
Чтобы избежать того, что я могу создать класс-оболочку для плагинов, эта оболочка реализует интерфейс, но тогда мне придется интенсивно редактировать каждый из плагинов, чтобы включитьпереопределение для каждого из многих методов API.
Пример кода (это не обязательно работает! Сейчас все в процессе перехода!):
Интерфейс (пример):
// In IPlugin.cs / IPlugin.dll
namespace Plugin
{
public interface IPlugin
{
// Many, many happy API things like this...
void SetupOptions(Hashtable options);
// (examples elided)
// And then these two... either one or the other
// is implemented, but not both.
XmlDocument RunPlugin(Updater u);
XmlDocument RunPlugin();
}
}
Вызываемая сборка ... У меня есть лотов из них.Я могу добавить ": IPlugin" довольно легко.Очевидно, что он не скомпилируется, потому что он не реализует один аргумент RunPlugin()
.
namespace Plugin
{
public class FileMaintenance : IPlugin
{
public void SetupOptions(Hashtable options)
{ // Code elided
}
public XmlDocument RunPlugin()
{ // Code elided
}
}
}
И, наконец, вызывающий код.Вот как это выглядело в коде отражения:
public XmlDocument RunPlugin(PluginRunner.Updater u)
{
Type [] paramTypes = new Type [0];
MethodInfo runInfo = repType.GetMethod("RunPlugin", paramTypes);
if (runInfo == null)
{
paramTypes = new Type [1];
paramTypes[0] = u.GetType();
runInfo = repType.GetMethod("RunPlugin", paramTypes);
if (runInfo == null)
throw new Exception;
}
Object[] parameters;
if ( paramTypes.Length == 0)
parameters = new Object[0];
else
{
parameters = new Object[1];
parameters[0] = u;
}
Object returnVal;
try
{
returnVal = runInfo.Invoke(repObj,parameters);
}
catch (Exception e)
{
}
// Rest of code omitted
}
Помните: я ищу хороший баланс между правильным способом исправить этот старый код и минимальным количествомредактирование кода вручную.