【问题标题】:Why do I need a recompiled page when a method used by it changes?当它使用的方法发生变化时,为什么我需要重新编译页面?
【发布时间】:2012-02-03 10:30:14
【问题描述】:

我有一个 aspx 页面,它使用了 App Code 文件夹 doSomething(int[] x) 中的一个类中的方法。我将函数定义更改为使用 IEnumerable 而不是数组:doSomething(IEnumerable<int> x)。接下来,我预编译了网站,使用“允许网站可更新”,并发布了新的 App_Code.dll。现在,页面的预编译版本在运行时会出现服务器错误:“找不到方法”。
如果我还发布为页面生成的 DLL,“App_Web_[page].aspx.[random].dll”,它可以工作。所以看起来函数的签名以某种方式嵌入到编译页面中......?为什么会这样,在更改现有代码时有没有办法避免这个问题?
每当我更改公共类中的代码时,我都不想更新所有页面 DLL。

【问题讨论】:

标签: c# asp.net web-site-project


【解决方案1】:

当一个页面被编译时,它会查看所有的方法签名并基本上锁定它们。如果您更改了正在调用的方法的签名,则页面将无法找到它,直到重新编译为止。

例如,假设您有一个类似的类

public class Dog {
  public void Walk(Int32 distance) {
    /// blah blah
  }
}

你在后面的页面代码中调用它:

protected void MyButtonClick(....) {
  Dog d = new Dog();
  d.Walk(3000);
}

当它编译下来时,页面将期望一个带有 Int32 签名的 walk 方法。

现在,假设我们将 Dog 类中的 walk 方法更改为:

public void Walk(Int16 distance) {
  // blah blah
}

(是的,愚蠢的改变,但它突出了问题)。 此时页面将无法找到采用 Int32 参数的 Walk 方法,因此会按原样崩溃。


只部署您认为需要的一个程序集可能看起来不错,但事实是代码中可能发生了任意数量的更改,因此这是一种非常糟糕的做法。

最好确保整个项目是一致的。甚至更大的网站也不需要那么长时间来部署。

当然,我认为使用网站项目本身就是不好的做法。将未编译的代码部署到服务器(非常糟糕),VS 搜索您的驱动器以更新项目中的引用,即使您已明确告诉它要使用哪个程序集(通常出乎意料,永远不会好 em>),所有主要代码都在一个通用的 app_code 文件夹中(limiting),等等。我可以在这里继续......

【讨论】:

  • 这是一个很好的答案。我试图通过将版本控制系统的日志处理成要上传的文件列表来缓解代码中未知更改的问题。这样,我就可以确切地知道哪些文件发生了变化以及哪些编译文件需要发布。或者我是这么想的……
【解决方案2】:

如果它是一个 Web 应用程序,那么每次更改服务器端代码时都需要重新编译 - 无论它是在单独的程序集中还是在 Web 应用程序的 App_Code 文件夹中。

只有网站(不是网络应用程序)允许您在不重新编译的情况下更改代码。

【讨论】:

  • 您是使用发布工具发布网站还是在调试?如果您已发布,则每次都需要重新发布。
  • 这不太正确,“网站”项目是由运行时根据请求动态编译的,因此它们只是不明确地编译。 MSDNmsdn.microsoft.com/en-us/library/ie/ms366723.aspx
  • 我正在发布。 (直接使用 MSBuild,但结果是一样的。)我知道我需要重新编译 everytime,但不是 everything。问题是为什么当它使用的代码发生变化时我需要重新编译页面。
  • 你说得对 Lloyd,我错过了可以在 web.Config 中的 Pages 部分声明的编译模式,或者直接在页面中声明。
  • Protector One - 您可能需要浏览下面的链接,因为它很好地描述了编译过程以及您的应用程序会发生什么。 asp.net/web-forms/tutorials/deployment/…
【解决方案3】:

您需要重新编译,因为您的页面已发布并输出到 bin 文件夹中的 dll。此 dll 正在寻找具有以下签名的方法:

doSomething(int[])

而且它已经不存在了。当您发布时,每次都更新所有内容。


我相信“可更新”标志允许您更新您的 aspx 代码(即标记),但代码隐藏文件将被编译掉。

【讨论】:

    【解决方案4】:

    以下几种更改可能会导致运行时异常:
    更改方法的签名或属性的类型。如果 受影响的成员被一个已经编译的页面引用,一个 将抛出异常。一些签名更改不会导致 如果重新编译整个站点,则会出现编译或运行时错误。为了 例如,.aspx 页面中的代码 Response.Write(ClassA.MethodA() 无论 MethodA 返回 int 还是 short 都将编译并运行良好。 但是如果 .aspx 页面已经编译并且你改变了返回 MethodA 类型从 int 到 short 无需重新编译,运行时 将抛出异常,因为编译的代码需要 int 签名。

    来自http://msdn.microsoft.com/en-us/library/ms366723.aspx#sectionToggle5

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-13
      相关资源
      最近更新 更多