• Attribute应用,简化ANF自定义控件初始化过程


    研究ANF的源码,让我获益良多。其中很多思想,都是非常值得学习的。其中换肤的方式,宝玉已经介绍过了,《Asp.Net Forums2.0深入分析》之 Asp.Net Forums是如何实现代码分离和换皮肤的。不过,当一个自定义控件中服务器端控件比较多的时候,InitializeSkin方法的实现代码就有点烦人了,比如看一下AdminSiteSettings的代码。实在是非常之烦人。模式都一样,如TextBox DisableSiteReason=skin.FindControl("DisableSiteReason") as TextBox之类。所以今天想利用Attribute来简化一下。

    首先我们要添加一个Attribute类,暂且就叫做BindControlAttribute:

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Reflection;

    namespace AspNetForums.Controls
    {
        [AttributeUsage(AttributeTargets.Field|AttributeTargets.Property,AllowMultiple=false)]
        class BindControlAttribute:Attribute
        {
            string _ctrlID;
            public BindControlAttribute(string ctrlID)
            {
                _ctrlID = ctrlID;
            }
            public string ControlID
            {
                get { return _ctrlID; }
            }
        }
    }

    这个类Attribute功能比较简单,就是让这个Attribute记录字段要绑定到的控件的ID。

    第二步就是修改SkinnedForumWebControl了,主要是添加一个方法:
                private void InitializeFields(Control skin)
                {
                    FieldInfo[] fields = this.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly);
                    foreach (FieldInfo fi in fields)
                    {
                        if (fi.IsDefined(typeof(BindControlAttribute), false))
                        {
                            BindControlAttribute bind = fi.GetCustomAttributes(typeof(BindControlAttribute), false)[0] as BindControlAttribute;
                            object ctrl = skin.FindControl(bind.ControlID);
                            fi.SetValue(this, ctrl);
                        }
                    }
                }
    其实在fi.IsDefined(typeof(BindControlAttribute), false)这里我本想再加一个条件的,就是限制字段的类型是System.Web.UI.Control或者它的子类,可是试了几种方法,都没能成功。请知道的指点一下...
    记得要引用System.Reflection名称空间,还要改一下CreateChildControls方法的实现:

      protected override void CreateChildControls()
      {
       Control skin = null;

       if (inlineSkin != null)
       {
        inlineSkin.InstantiateIn(this);

        InitializeSkin(this);

       }
       else
       {
        // Load the skin
        skin = LoadSkin();
                    //Initialize the fields
                    InitializeFields(skin);//就加这一行
        // Initialize the skin
        InitializeSkin(skin);

        Controls.Add(skin);
       }
      }

    到这里,实现的任务就完成了。下面就是应用了。应用是比较简单的,只需要在定义字段的时候,加上这个BindControlAttribute就行了。如:
    uing System;
    using System.Collections;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using AspNetForums.Components;
    using AspNetForums.Enumerations;

    namespace AspNetForums.Controls
    {
     /// <summary>
     /// 论坛组列表服务器控件
     /// </summary>
     public class ForumGroupView : SkinnedForumWebControl
     {
      #region 成员字段

      private ForumContext forumContext = ForumContext.Current;
      private string skinFilename = "View-ForumGroupView.ascx";
      [BindControl("forumGroupRepeater")]//定义字段时加这么一行
      private Repeater repeater;

      #endregion

      public ForumGroupView()
      {
       // Assign a default template name
       if (SkinFilename == null)
        SkinFilename = skinFilename;

      }

      #endregion

     

       #region 控件初始化

      // *********************************************************************
      //  Initializeskin
      //
      /// <summary>
      /// Initializes the user control loaded in CreateChildControls. Initialization
      /// consists of finding well known control names and wiring up any necessary events.
      /// </summary>
      ///
      // ********************************************************************/
      protected override void InitializeSkin(Control skin)
      {
       //repeater = (Repeater) skin.FindControl("forumGroupRepeater");//这一行就没有用了。

       DataBind();

      }

      感觉是不是好点呢?

    第一次用反射,着实费了我不小的功夫(主要是看书不认真:-))。我要获取私有字段的时候,试了好多次才试出来,前面2个BindingFlags貌似都得加上。另外,我发现,Attribute构造函数是在调用GetCustomAttributes函数时才调用的。不知道是否有二班的情况呢?

  • 相关阅读:
    Linux 服务器 个人常用操作命令记录
    Thinkphp5.0 自定义命令command的使用
    vue初学之node.js安装、cnpm安装、vue初体验
    php实现在不同国家显示网站的不同语言版本
    array_map、array_walk、array_filter三个函数的区别
    实现简单点赞功能
    SQL语言-----数据操作
    SQL语言
    MySQL高可用架构之Keepalived+主从架构部署
    MyCAT源码分析——分析环境部署
  • 原文地址:https://www.cnblogs.com/bqrm/p/1203366.html
Copyright © 2020-2023  润新知