gpt4 book ai didi

asp.net - 如何最佳拦截 ASP.NET 用户控件子树中所有元素的解析

转载 作者:行者123 更新时间:2023-12-04 12:32:21 26 4
gpt4 key购买 nike

我想拦截我自己的用户控件的整个子树中每个控件的解析。

目前我已经覆盖了 protected 方法 Control.AddParsedSubObject在我的用户控制中。它仅限于在声明性语法中拦截对直接子控件的解析,因为这些控件中的每一个都有自己的 AddParsedSubObject方法来进一步解析它自己的子控件。

从用户控件我无法进入 child 的 child 来拦截那些解析调用。

在我的用户控件的以下声明性示例中,我可以从用户控件的 AddParsedSubObject 覆盖内部访问 tv 对象。

<asp:TreeView runat="server" id="tv" />

但是,我无法访问以下示例中的 tv 对象(或第一个面板的其他子项),因为该解析由面板或其子项处理。
<asp:Panel runat="server">
<asp:TreeView runat="server" id="tv" />
<asp:Panel runat="server">
<asp:TextBox runat="server" />
</asp:Panel>
</asp:Panel>

我在用户控件中的代码隐藏如下所示
    // User control interception of its parsed children 
protected override void AddParsedSubObject(object obj) {

// Do some custom work with the control object.
if (obj is Control && ((Control)obj).ID == "tv") {
TreeView tv = (TreeView)obj;
DoSomethingWithParsedObject(tv);
}

// Let ASP.NET continue and put the control in the page hierarchy
base.AddParsedSubObject(obj);
}

寻找有关如何拦截用户控件的整个子树中每个控件的解析的想法。例如,我想在每个解析步骤写出自定义信息。

最佳答案

如果您使用 .Net 4.5,有一个很好的方法来实现它。 Asp.Net 使用 ControlBuilder 从 aspx 布局构建临时 cs 文件。在 .Net 4.5 之前,您只能通过反射和切换 ControlBuilder 类中的一些内部静态变量来拦截它。

但是在 .Net 4.5 中,他们添加了新类 ControlBuilderInterceptor .然后你可以写这样的代码:

namespace TestInterceptApp
{
public class BuilderInterceptor : ControlBuilderInterceptor
{
public override void OnProcessGeneratedCode(ControlBuilder controlBuilder, CodeCompileUnit codeCompileUnit, CodeTypeDeclaration baseType,
CodeTypeDeclaration derivedType, CodeMemberMethod buildMethod,
CodeMemberMethod dataBindingMethod, IDictionary additionalState)
{
base.OnProcessGeneratedCode(controlBuilder, codeCompileUnit, baseType, derivedType, buildMethod, dataBindingMethod, additionalState);

buildMethod.Statements.Insert(
buildMethod.Statements.Count - 1,
new CodeSnippetStatement("TestInterceptApp.ControlInterceptor.Intercept(@__ctrl);"));
}
}
}

然后你需要修改 web.config 中的编译部分来注册这个类到 Asp.Net:
  <system.web>
<compilation debug="true" targetFramework="4.5" controlBuilderInterceptorType="TestInterceptApp.BuilderInterceptor"/>
</system.web>

然后你可以像这样编写这个拦截器类:
namespace TestInterceptApp
{
public static class ControlInterceptor
{
public static void Intercept(TreeView control)
{
// Do some custom work with the control object.
if (control.ID == "tv")
{
control.Nodes.Add(new TreeNode("Test"));
}
}

public static void Intercept(object obj)
{
// just ignore all others controls
}
}
}

基本上当 ControlBuilder 创建新的 cs 文件时,它会插入这一行
    "TestInterceptApp.ControlInterceptor.Intercept(@__ctrl);"

到每个控制生成块的末尾。您可以使用对象参数在 ControlInterceptor 类中定义一个方法,或者您可以使用特定参数进行几个所需的重载。并加上一个带有对象参数的基本方法。当 CLR 执行它时,如果控件是 TreeView,那么它会将它发送到正确的方法。对于所有其他控件,如 Literal、Button、HtmlHead、Page 等,CLR 将使用带有对象签名的方法。

我的示例只是将新的 TestNode 添加到当前应用程序中 ID="tv"的每个 TreeView。 ControlBuilder 生成的代码是这样的:
    [System.Diagnostics.DebuggerNonUserCodeAttribute()]
private global::System.Web.UI.WebControls.TreeView @__BuildControltv() {
global::System.Web.UI.WebControls.TreeView @__ctrl;

#line 32 "c:\users\someuser\documents\visual studio 11\Projects\TestInterceptApp\TestInterceptApp\Default.aspx"
@__ctrl = new global::System.Web.UI.WebControls.TreeView();

#line default
#line hidden
this.tv = @__ctrl;
@__ctrl.TemplateControl = this;
@__ctrl.ApplyStyleSheetSkin(this);

#line 32 "c:\users\someuser\documents\visual studio 11\Projects\TestInterceptApp\TestInterceptApp\Default.aspx"
@__ctrl.ID = "tv";

#line default
#line hidden

#line 32 "c:\users\someuser\documents\visual studio 11\Projects\TestInterceptApp\TestInterceptApp\Default.aspx"
this.@__BuildControl__control3(@__ctrl.Nodes);

#line default
#line hidden
// here is that line that we added via ControlBuilderInterceptor
TestInterceptApp.ControlInterceptor.Intercept(@__ctrl);
this.@__PageInspector_SetTraceData(new object[] {
@__ctrl,
null,
1838,
368,
false});
return @__ctrl;
}

关于asp.net - 如何最佳拦截 ASP.NET 用户控件子树中所有元素的解析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20524428/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com