zoukankan      html  css  js  c++  java
  • 自定义服务器控件通过反射调用页面方法

      今天突然想把某一功能封装成服务器控件,但这一功能又需要连接数据库,如果直接在控件里连接数据库,那么跟在UI层直接操作数据库是一样的,也就破坏了三层架构。

      突然想到了在自定义控件里调用页面方法,但在控件里只能调用基类 System.Web.UI.Page 已声明的几个方法,比如:DataBind()。一个简单方法就是在自定义控件里调用基类已声明的方法,然后在具体页面重写此方法,达到功能的实现。这里简单介绍一下:

    在自定义控件里可以这样调用

    this.Page.DataBind();
    在具体页面重写此方法:
        public override void DataBind()
        {
            
    base.DataBind();
            
    //Do something 
        }
     
      但很明显我今天要介绍的不是此方法。以下进入正题。
      想用反射调用页面方法,如果有规范的方法名和参数列表,那就简单多了。这里自然想到用一接口来规范化。
      一、创建新网站(ServerControlTest)
      二、添加自定义服务器控件项目
        
      三、定义并在页面实现接口
        为了方便,直接在 Default.aspx.cs 文件中声明接口。注意:这里的接口是不包含在任何命名空间中的。
        此时Default.aspx.cs 文件中的代码如下:
    using System;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;

    public partial class _Default : System.Web.UI.Page , ITestInterface
    {
        
    protected void Page_Load(object sender, EventArgs e)
        {

        }

        
    //接口实现
        #region TestInterface 成员
        
    public string TestMethod(string str)
        {
            
    return "已调用接口:TestInterface —— " + str;
        }
        
    #endregion
    }
    //接口定义
    public interface ITestInterface
    {
        
    string TestMethod(string str);
    }

      四、自定义控件的实现

        我们将重载控件的 OnInit 事件,在此事件中调用页面方法 TestMethod。如果此页面未实现 ITestInterface 接口,我们将抛出异常。

        控件的默认代码不变,添加以下代码:

            protected override void OnInit(EventArgs e)
            {
                
    base.OnInit(e);

                Type myType 
    = this.Page.GetType();
                System.Reflection.TypeFilter myFilter 
    = new System.Reflection.TypeFilter(MyInterfaceFilter);
                
    // 返回页面名称为 ITestInterface 的接口
                Type[] myInterfaces = myType.FindInterfaces(myFilter, "ITestInterface");
                
    //已实现接口
                if (myInterfaces.Length > 0)
                {
                    
    //我们将调用方法得到的结果赋于控件的 Text 属性
                    
    //第一个参数是调用此TestMethod的对象,在这里自然是页面实例
                    
    //第二个参数是方法TestMethod的参数列表,类型必须一致,无参数时可传null
                    this.Text = myInterfaces[0].GetMethod("TestMethod").Invoke(this.Page, new object[] { "输入参数" }).ToString();
                }
                
    //未实现接口
                else
                {
                    
    throw new Exception("The page doesn't implement the interface 'ITestInterface' !");
                }
            }
            
    public bool MyInterfaceFilter(Type typeObj, Object criteriaObj)
            {
                
    if (typeObj.ToString() == criteriaObj.ToString())
                    
    return true;
                
    else
                    
    return false;
            }

      五、为项目 ServerControlTest 添加引用

      

      六、在 Default.aspx 中引用控件

    <%@ Page Language="C#" AutoEventWireup="true"  CodeFile="Default.aspx.cs" Inherits="_Default" %>
    <%@ Register Assembly="ServerControl" Namespace="ServerControl" TagPrefix="cc1" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        
    <title></title>
    </head>
    <body>
        
    <form id="form1" runat="server">
        
    <div>
            
    <cc1:ServerControl1 ID="ServerControl1" runat="server" />
        
    </div>
        
    </form>
    </body>
    </html>

      七、运行应用程序

        页面将输出: 已调用接口:TestInterface —— 输入参数

     

    至此已介绍完毕。不过其中有些注意的地方提一下。

    在查找接口时 Type[] myInterfaces = myType.FindInterfaces(myFilter, "ITestInterface"); 接口名必须是完全限定名,如果接口是存放在某一命名空间中就必须注意了。如果你觉得这样太过于局限的话,那么你可以为控件增多一个属性,用来输入接口的完全限定名。

    大家如果有什么更好的方法或建议,不妨提出来,大家一起学习学习。

  • 相关阅读:
    CentOS-6.8 最详细安装教程(贴镜像文件+多图)
    SSM 框架整合完整流程讲解(IDEA + Maven)
    【万字长文】Spring MVC 层层递进轻松入门 !
    Spring AOP 由浅入深学习教程【新手向】
    Spring 注解和XML两种方式配置IOC
    【万字长文】Spring框架 层层递进轻松入门 (IOC和DI)
    用idea搭建SSM项目,原来这么简单
    Java并发编程:什么是CAS?这回总算知道了
    Java并发编程:Java的四种线程池的使用,以及自定义线程工厂
    Java并发编程:Java线程池核心ThreadPoolExecutor的使用和原理分析
  • 原文地址:https://www.cnblogs.com/lucas/p/1430345.html
Copyright © 2011-2022 走看看