设计器打开表单时出现MissingMethodException错误;运行时正常。

4
假设我有一个名为A的项目,其中包含一个类A和该类的属性如下:
    public bool IsConnected
    {
        get { return m_isConnected; }
        private set { m_isConnected = value; }
    }
在同一个解决方案中,我有一个名为B的项目引用了项目A,并且拥有一个名为Login的用户控件。该控件具有以下属性:
    private A m_A = null;
Login的构造函数中,我进行了以下调用:

if (m_A != null && m_A.IsConnected) { ... }

在同一个项目中,主窗体上有一个用户控件A,该控件是使用表单设计器添加的。程序运行良好,并且该属性被正确读取。
然而,在设计器中打开主窗体时,我会遇到以下异常: MissingMethodException: 'Boolean A.get_IsConnected()'
注释掉m_A.IsConnected可以让我使用设计器,但这变得非常烦人。有时似乎它随机地起作用。
有什么想法吗?

有趣的事情,我刚发现将 m_A.IsConnected 包装到一个方法中会移除异常(在构造函数中始终失败的 m_A != null): private bool GetIsConnected() { return m_A.IsConnected; } - Nicolas Rousseau-Dupuis
4个回答

0

正如Ari Roth所指出的那样,DesignMode无法正常工作。为了弥补这一点,我使用了这个扩展方法:

public static bool IsDesignTime(this Control control)
{
    if (LicenseManager.UsageMode == LicenseUsageMode.Designtime)
    {
        return true;
    }

    if (control.Site != null && control.Site.DesignMode)
    {
        return true;
    }

    var parent = control.Parent;
    while (parent != null)
    {
        if (parent.Site != null && parent.Site.DesignMode)
        {
            return true;
        }
        parent = parent.Parent;
    }
    return false;
}

按照Simon Linder所描述的方式使用它。


0

你可以使用以下方法,而不是将其注释掉:

if (this.DesignMode)
{
    return;
}

或者

if (!this.DesignMode)
{
    if (m_A != null && m_A.IsConnected) { ... }
}

编辑: 我记得曾经遇到过单例类的问题。问题是单例始终被初始化,尽管构造函数从未调用过。如果我正确理解了您的问题,你的问题也是如此。您的成员m_A永远不会为NULL,但实际上它应该为NULL。
我通过以下方法解决了我的问题:
在Visual Studio中选择“工具\选项...\调试\常规”,然后禁用“启用属性计算和其他隐含函数调用”,并启用“跳过属性和运算符(仅限托管代码)”。
希望这可以帮助您。


我一直在寻找这样的东西,谢谢!不幸的是,这个解决方法并没有改变任何东西,这很奇怪。我还要补充一点,在构建时m_A始终为null,因此IsConnected属性永远不应该被读取。 - Nicolas Rousseau-Dupuis
请记得先调用InitializeComponents()函数。 - Simon Linder
InitializeComponents() 被首先调用,即使 !this.DesignMode 和 m_A != null 都应该失败,仍然会出现异常。 - Nicolas Rousseau-Dupuis

0

过去有人告诉我,this.DesignMode并不总是完全可靠的。你可以使用的另一个选项是预处理器指令:

#if DESIGN
return;
#else
if (m_A != null && m_A.IsConnected) { /* etc. */ }
#endif

然后添加一个名为DESIGN的条件编译符号,你就可以了。


我很想从根本上解决这个问题,但现在我会采用这个解决方法。谢谢! - Nicolas Rousseau-Dupuis

0

看起来设计师正在使用旧版本的控制DLL,该版本没有IsConnected属性。

MissingMethodException异常与m_A的值无关。这是JIT编译器抱怨缺少该属性。如果将对m_A.IsConnected的调用包装在方法中,则可以正常工作,因为不会调用此方法(因为m_A确实为null),因此不会被JIT编译,因此不需要IsConnected属性。

当您将控件放入VS中的表单中时,设计师会在表单中创建您控件的“真实”实例,该实例调用构造函数,从而导致JIT编译问题。


将调用包装在另一个函数中,就像你所说的那样,是可行的。然而,我不明白设计师如何使用旧的DLL,因为我已经重建了很多次一切... - Nicolas Rousseau-Dupuis
不幸的是,我也不知道。如果您在GAC中有一个旧版本,这可能会解释它,但运行时也无法工作。 我猜你也离开了VS,删除了obj和bin目录并重新启动了VS。 - Timores

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接