即使条件为真,也会解决条件的错误部分

时间:2013-03-22 21:24:21

标签: c# reflection dll

我最近不得不更改一段代码以允许与旧版DLL兼容。 DLL具有相同的名称,未签名。不同之处还在于添加到新DLL的一些其他方法。

对我来说似乎不对的一种方法是在项目中引用新的DLL,构建并运行。如果要使用其他DLL,只需将其替换为bin文件夹即可。您可以通过使用Reflection在某个构造函数中检查方法是否存在来避免错误,并设置一个标志,以便稍后您可以避免在使用旧版本时调用新函数。

对我来说奇怪的是,使用旧版本时,下面的代码不起作用:

int[] someVariable = (DLLIsNewFormat) ? DLL.CallNewMethod() : new int[5];

基本上发生的事情是DLLIsNewFormat是False但由于某种原因我收到错误:

  

找不到方法:'Int32 [] [NameSpace]。[Class] .CallNewMethod()'。

我知道解决这个问题的最佳方法是检查每个函数是否存在,然后使用反射调用它们。但我只是不知道代码为什么会这样。这只是未定义的行为吗?

2 个答案:

答案 0 :(得分:0)

你想要的是隐藏对JIT中不存在的方法的调用。

为此,您需要确保在函数内部进行的每个不存在的调用以及调用这样的函数都由版本条件控制:

private int[] WrappedNewMethod()
{
  return DLL.CallNewMethod();
}

...SomeOtherMethod()
{
   int[] someVariable = (DLLIsNewFormat) ? WrappedNewMethod(): new int[5];
}

答案 1 :(得分:0)

在包含您的代码段的方法是JIT编译时发生这种情况。为了进行JIT编译,该方法需要在调用方法时可用。由于该方法不可用,因此在方法执行之前调用包含此代码的方法时,JIT编译器会抛出此异常。

解决这个问题的一种方法是定义一个新方法:

int[] HideCall()
{
    return DLL.CallNewMethod();
}

然后直接调用此方法而不是DLL.CallNewMethod()

更好的解决方案是在程序集中定义一个接口,该接口由“条件DLL”和有条件地使用此DLL的程序集引用。在主程序集中提供此接口的默认实现,以及在有条件使用的DLL中使用备用实现。

然后,在运行时,您可以简单地查看DLL是否可用,使用反射来构造实现此接口的类的实例,然后用这个替换出对默认实现的引用。

示例代码:

// Interface, in an assembly visible to both of the other assemblies.
public interface IDLLInterface
{
    int[] CallNewMethod();
}

// Implementation in the main program.
class DefaultDLLImplementation : IDLLInterface
{
    public int[] CallNewMethod()
    {
        return new int[5];
    }
}

static class DLLImplementation
{
    public readonly IDLLInterface Instance;

    static DLLImplementation()
    {
        // Pseudo-code
        if (DllIsAvailable) {
            Instance = ConstructInstanceFromDllUsingReflection();
        } else {
            Instance = new DefaultDLLImplementation();
        }
    }
}

然后您可以使用DLLImplementation.Instance.CallNewMethod()代替,并自动调用正确的方法。

当然,我建议使用更具描述性的名称命名您的界面,以便明确其含义。

相关问题