【发布时间】: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我无法理解你的意思?您的意思是用户控件标记文件中的
CodeFile或CodeBehind属性?
标签: c# asp.net user-controls webusercontrol dynamic-compilation