【问题标题】:Loading ASCX control created dynamically (via code)加载动态创建的 ASCX 控件(通过代码)
【发布时间】:2012-04-30 17:05:43
【问题描述】:

我正在通过代码创建Web User Controls(我的 C# 代码写出标记、代码隐藏和设计器文件在回调时写入磁盘)。控件都创建得很好。我可以将它们添加到我的网络项目中并将它们放在一个页面上。

当我尝试使用 LoadControl(path) 加载控件时,它会说:

Unable to load type 'MyNameSpace.UseControlClass'

这是因为控件尚未编译。

但我的要求是动态加载控件而不重新编译解决方案。

如何只在创建控件文件时编译用户控件?因为这似乎是唯一的出路。

编辑:- 我的猜测是,由于该文件尚未编译,但运行时不允许加载它。我尝试使用CodeDom 编译器编译代码文件。喜欢:

var filePath = Server.MapPath(path);
var provider = CSharpCodeProvider.CreateProvider("C#");
var opts = new CompilerParameters(new[] { "mscorlib.dll", "System.Web.dll", 
                              "Telerik.Web.Design.dll", "Telerik.Web.UI.dll", 
                              "Telerik.Web.UI.Skins.dll", "MyCurrentDll.dll"});
opts.GenerateExecutable = false;
opts.GenerateInMemory = true;
var cr = provider.CompileAssemblyFromFile(opts, new string[] { filePath+".cs" });

但它抱怨cannot find metadata file Telerik.Web.Design.dll 等。我不想硬编码telerik 路径,因为它在托管系统中可能不同(尽管它在当前网络应用程序的bin 中)。 MyCurrentDll.dll 也是我从中编译代码文件的文件的 dll。我该如何解决这个问题?

我的想法是编译代码文件动态创建一个dll 并将其复制到Web 应用程序的bin 目录。它可能会解决我最初所说的问题。

EDIT 2:- 经过试用后,我能够动态编译代码文件并生成dll。即使在生成 dll 并将其放入我的应用程序的bin 之后,我也无法使用virtual path 加载用户控件。我尝试了以下方法:

var asm = Assembly.Load("ddlPath");
var t = asm.GetType(fullTypeName);//NameSpace.Class
var ctrl = LoadControl(t,null);

在此之后加载 ctrl。我分配其Id 属性并将其添加到asp.net Panel 控件。但回发后不可见:(

现在我要么必须以某种方式使动态编译的 dll 的类型可用于运行时(可能是应用程序域),以便当我使用虚拟路径加载控件时,它会正确加载并且我没有得到 HtmlParseException 或找出原因加载控制表单Type 未显示。

PS:- 我已经使用Type 加载了一个Label 控件并且它工作正常。

【问题讨论】:

  • 这是一个非常有趣的问题。我想不出一个用例 - 但我通常处理这个的方式是让另一个程序集知道如何构建控件并在运行时发出 HTML 等。通过将新控件嵌入到另一个程序集中,然后您可以从中编译和加载,也许在这里可以采用类似的方法?我会感兴趣地看这个问题!
  • @dash 用例是我们允许用户对一些字段(具有预定义的输入类型)进行分组并从最终用户那里获取输入。我想创建一个用户控件,嵌入这些字段。
  • 您的控件和托管页面是否在 CodeFile 中而不是 CodeBehind 中?
  • 您是否尝试过将用户控件放在同一解决方案中的其他项目中?您可以在主项目中配置输出dll到bin。
  • @user551263 如何在托管在服务器上的网站中执行此操作? @jbl我无法理解你的意思?您的意思是用户控件标记文件中的CodeFileCodeBehind 属性?

标签: c# asp.net user-controls webusercontrol dynamic-compilation


【解决方案1】:

最后我能够解决这个问题。以下是我采用的策略:

  1. 创建包含CodeBehindMarkupDesigner代码结构的文本文件
  2. 阅读有关要创建哪些字段的信息。
  3. 为字符串生成器中所需的控件添加标记。
  4. 将一些其他相关信息放入更多的字符串构建器中
  5. 写入文件

在此之后,我使用CodeDome 编译器创建了dll。如问题的 Edit 部分所述,编译过程中面临的主要问题是找不到引用的程序集,这是通过将 bin 目录路径的路径与 dll 文件名一起解决的,例如:

Server.MapPath("~/bin")+"\\Telerik.Web.dll"

等等

EDIT2 中概述的下一个问题要简单一些。有相当愚蠢的。嵌入在动态生成的用户控件中的另一个用户控件存在问题。

即使在此之后,我也无法将控件加载到我编译代码的页面中。当我在另一个页面中加载控件时,这个问题得到了解决。运行时能够从动态编译的dll 解析类型。

【讨论】:

    【解决方案2】:

    嗯..您是否考虑过为此使用App_Code folder

    包含共享类和业务对象的源代码(用于 例如,..cs 和 .vb 文件)作为您的一部分进行编译 应用。在动态编译的网站项目中,ASP.NET 根据初始请求编译 App_Code 文件夹中的代码 你的申请。此文件夹中的项目会在任何时候重新编译 检测到更改。

    【讨论】:

    • 这对我没有帮助,因为我正在创建用户控件并且文件也是在运行时动态创建的。问题是在应用程序域中加载创建的文件以创建控制对象。我已经解决了,很快就会发布答案。
    猜你喜欢
    • 1970-01-01
    • 2011-01-04
    • 2011-06-03
    • 2012-03-19
    • 1970-01-01
    • 2016-06-18
    • 2010-11-20
    • 2010-10-24
    • 1970-01-01
    相关资源
    最近更新 更多