C#_特性&反射详解

特性是什么?

为程序元素额外添加声明信息的一种方式。

字面理解:相当于把额外信息写在干胶标签上,然后将其贴在程序集上。

反射是什么?

反射是一种能力,运行时获取程序集中的元数据。

字面理解:程序运行时,被加载到内存中,就会产生应用程序域(AppDomain),里面就是Assembly(程序集);反射就是读取程序集中的元数据。

元数据(metadata):是用来描述数据的数据或者叫做信息的信息,就是程序集中的类、属性、方法、特性等的说明信息。

应用案例

namespace MyWorkBook.MyTest
{
    public partial class FormAttribute : Form
    {
        private List<Type> heroTypes; //保存所有英雄类的类型
        private object selectedHero;  //当前选择的英雄对象

        public FormAttribute()
        {
            InitializeComponent();

            //加载所有英雄的类型--通过当前执行代码的程序集,获取程序集中所有类型,根据自定义特性进行筛选英雄并转换成集合类型,
            heroTypes = Assembly.GetExecutingAssembly().GetTypes()
                .Where(t => t.GetCustomAttributes(typeof(HeroAttribute),false).Any()).ToList();

            //初始化英雄列表
            heroListBox.Items.AddRange(heroTypes.Select(t => t.Name).ToArray());

        }

        private void heroListBox_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (heroListBox.SelectedIndex == -1) return;//如果未选定任何项退出

                //创建当前选择的英雄对象
                var selectedHeroType = heroTypes[heroListBox.SelectedIndex];//根据当前选中项获取索引(集合下标)。
                selectedHero = Activator.CreateInstance(selectedHeroType);//

                //获取该英雄类型的所有技能方法
                var skillMethods = selectedHeroType.GetMethods()
                    .Where(m => m.GetCustomAttributes(typeof(SkillAttribute),false).Any()).ToList();

                //初始化技能列表
                skillListBox.Items.Clear();
                skillListBox.Items.AddRange(skillMethods.Select(m => m.Name).ToArray());
            
        }

        /// <summary>
        /// 双击组件(技能列表)触发事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void skillListBox_DoubleClick(object sender, EventArgs e)
        {
            if(skillListBox.SelectedIndex == -1) return;
            //获取当前选择的技能方法
            var selectedSkillMethed = selectedHero.GetType().GetMethod(skillListBox.SelectedItem.ToString());

            //调用该技能方法
            selectedSkillMethed?.Invoke(selectedHero, null);
        }
    }

    [Hero]//②贴上标签
    class 段誉
    {
        [Skill]
        public void 六脉神剑()
        {
            MessageBox.Show("段誉 - 六脉神剑", "提示");
        }

        [Skill]
        public void 凌波微步()
        {
            MessageBox.Show("段誉 - 凌波微步", "提示");
        }
    }

    [Hero]//②贴上标签
    class 萧峰
    {
        [Skill]
        public void 降龙十八掌()
        {
            MessageBox.Show("萧峰 - 降龙十八掌", "提示");
        }

        [Skill]
        public void 打狗棍法()
        {
            MessageBox.Show("萧峰 - 打狗棍法", "提示");
        }
    }

    [Hero]//②贴上标签
    class 虚竹
    {
        [Skill]
        public void 小无相功()
        {
            MessageBox.Show("虚竹 - 小无相功", "提示");
        }

        [Skill]
        public void 折梅手()
        {
            MessageBox.Show("虚竹 - 折梅手", "提示");
        }
    }

    /*①定义标签
        特性名规范:自定义名称+Attribute后缀
        类中没有任何成员(可以添加成员,通过反射获取),在反射代码中通过名称知道标签作用
        */

    public class HeroAttribute : Attribute 
    {

    }

    public class SkillAttribute : Attribute
    {

    }

}

万物皆是对象,对象均可反射。

 

 内外部使用私有成员会打破对象的封装性,并且可能导致代码执行不稳定,所以一般情况不建议使用反射来访问私有成员;但是在某些场景使用反射是必要的,例如:

1.在某些调试场景需要访问私有成员来查找问题。

2.在测试代码时,需要访问私有成员来验证代码正确性。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值