【发布时间】:2011-03-07 09:28:00
【问题描述】:
我有一些严格使用反射实现的旧 C# 插件代码。在修复一些 C# 2.0 -> 4.0 兼容性问题 ("Load from Remote Source") 时,我决定摆脱旧的反射代码并用接口替换它。需要该接口是因为现在需要将插件加载到它们自己的 AppDomain 中,然后进行编组。
我可以浏览数百个插件的源代码,并通过简单的搜索和替换让它们全部实现新的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
}
请记住:我正在寻找正确的方法来修复这个旧代码和手动编辑代码的最少数量之间的平衡。
【问题讨论】:
-
在反射代码中,您会发现一个方法接受一个参数,该参数的类型是提供的更新程序实例的运行时类型;这很重要吗? (是否有Updater的子类,有些插件只处理特定的子类?)
-
在旧的反射代码中,它只是在寻找一种方法,要么不实现参数,要么真正实现。在这种情况下,类型(“updater”)并不重要。
标签: c# api reflection interface