我有一个引用第三方dll的C#dll。有第三方dll的不同版本。
如您所料,如果最新的第三方dll存在,我想使用新功能,如果不是我想执行旧功能。
我不知道如何实现这一点,但我认为首先要尝试的是一个简单的if语句来决定调用哪个函数。
所以我找到了程序集,获取它的位置,从而得到它的版本信息。 (我需要文件版本,因为产品版本是相同的)。
然后一个简单的
if (version >= 3) do x() else do y()
当我在安装了版本2的计算机上执行代码时,我得到MissingMethodException
x()
。我以为我犯了一个愚蠢的错误,但逻辑是正确的。版本为2,因此不应执行x();
。我决定删除有问题的方法,并用throw new Exception()
替换它。不抛出异常并且代码成功完成。
这是危险 - 我认为这是由于分支预测。这很危险,因为它不是我所知道的领域,因此做出假设是危险的。
所以我的问题是:
我是以错误的方式解决这个问题 - 是否有一个我不知道的更明显的解决方案?
或
有没有办法禁用分支预测(如果这是原因)或以某种方式强制执行/标记if条件作为必须在继续之前执行的点。
以下是正在执行的代码:
MissingMethodException
方法x()
。x();
的调用并取消注释异常 - 不会抛出任何异常。相关代码:
Assembly assembly = System.Reflection.Assembly.GetAssembly(typeof(3rdPartyClass));
FileVersionInfo fileVersionInfo = FileVersionInfo.GetVersionInfo(assembly.Location);
if (fileVersionInfo.FileMajorPart >= 3)
{
// throw new Exception("aagghh");
x();
}
else
{
y();
}
答案 0 :(得分:2)
使用反射,可以获得特定DLL可用的方法列表(更具体地说:类型)。
您可以使用此methodinfo动态调用Vlad的解决方案中指定的方法。
事实上,您可以省略版本检查,然后尝试直接找到预期的方法。
var methodX = assembly.GetType("sometype").GetMethod("X");
if (methodX != null)
{
methodX.Invoke(params);
}
else
{
assembly.GetType("sometype").GetMethod("Y").Invoke(otherParams);
}
编辑:这不是您想要的,但通过这种反射,您可以找到正确的方法,也可以用于您自己的装配。
答案 1 :(得分:1)
没有“分支预测”:运行时绑定似乎是在执行方法时发生的。
所以解决方法就是这样:
if (fileVersionInfo.FileMajorPart >= 3)
{
CallX();
}
else
{
CallY();
}
void CallX()
{
DependentClass.X();
}
void CallY()
{
DependentClass.Y();
}
然而,无论如何这似乎是一个黑客攻击:你需要执行你链接的DLL版本。
答案 2 :(得分:0)
这实际上是一个更准确的答案:
Assembly assembly = System.Reflection.Assembly.GetAssembly(typeof(String));
FileVersionInfo fileVersionInfo = FileVersionInfo.GetVersionInfo(assembly.Location);
ObjectHandle oh = Activator.CreateInstanceFrom("AssemblyName.dll", "namespace.class");
object o = oh.Unwrap();
Type to = o.GetType();
if (fileVersionInfo.FileMajorPart >= 3)
{
to.InvokeMember("Method X", BindingFlags.InvokeMethod, null, o, null);
}
else
{
to.InvokeMember("Method Y", BindingFlags.InvokeMethod, null, o, null);
}