zoukankan      html  css  js  c++  java
  • c#中的特性,以及一些思考

    unity中会有像[range(0,1)]这样的特性写法,其非常方便的限制了变量范围但是。我一直很好奇这是怎么实现的,所以翻了翻其他博主对其的解释和应用。

    一,什么是特性

      有一种解释我很能接受,特性就像牡蛎附在对象上。其本质也是一种对象,特殊之处在于其编译时就存在了,也就是在程序运行之前就存在了。

    二,如何定义一个特性

     1 namespace UnityEngine
     2 {
     3 
     4     [AttributeUsage(AttributeTargets.Field, Inherited = true, AllowMultiple = false)]
     5 
     6     public abstract class PropertyAttribute : Attribute
     7     {
     8         protected PropertyAttribute();
     9 
    10         public int order { get; set; }
    11     }
    12 }

    只是啥=。= 不就是一个对象吗,我copy了unity中的一段特性代码。事实上所有的特性都继承 Attribute,unity在中多封装了一层 PropertyAttribute ,且给每个特性加上了一个ID。

    所以定义一个特性只需要继承 Attribute 就可以了。

    那么其上面的特性 AttributeUsage又表示什么呢,

    三,特性的使用

    AttributeUsage=。=直接说明了特性的使用范围嘛,后面标注了几个属性
    AttributeTargets.Field代表可以附着在字段上,其他地方不能加不上这个标签特性。AttributeTargets本身是枚举值,且其是c#预制的特性变量。
    Inherited 是否可以继承这就很好理解了
    AllowMultiple 是否能够混合使用,也就是一个类上挂俩三个特性。

    理解可这些参数之后就可以自己写一个特性玩玩了,这里我写一个自定义的debuginfo在unity中调用
    (1)声明
    using System;
    using UnityEngine;
    //特性所能使用的范围
    [AttributeUsage(AttributeTargets.Method|AttributeTargets.Field
        , AllowMultiple =true)]
    public class DebugerCoderAttribute : UnityEngine.PropertyAttribute
    {
        private string codename;
        private string codeLasttime;
        private bool Ischeck;
        private string message;
        public DebugerCoderAttribute(string CoderName, string CodeLastTime, bool Checked)
        {
            codename = CoderName;
            codeLasttime = CodeLastTime;
            Ischeck = Checked;
            message = "";      
        }
    
        public DebugerCoderAttribute(string CoderName, string CodeLastTime,string OtherInfo, bool Checked)
        {
            codename = CoderName;
            codeLasttime = CodeLastTime;
            Ischeck = Checked;
            message = OtherInfo;
        }
        public string ScriptsCoder
        {
            get
            {
                return codename;
            }
        }
        public string ScriptsTime
        {
            get
            {
                return codeLasttime;
            }
        }
        public bool ScriptsIsChecked
        {
            set
            {
                Ischeck = value;
            }
            get
            {
                return Ischeck;
            }
        }
        public string Message
        {
            set
            {
                   message = value;
            }
            get
            {
                return message;
            }
        }
    }

      (2)脚本调用

    public class TempReadJobScrpts : MonoBehaviour {
    
        [DebugerCoder("yang", "1995", false, Message = "只能注释方法名,在MyinfoDebug中可以修改完成指定位置信息读取")]
        public void MyMethod()
        {
    
        }
    }

    (3)反射调用(更好点可以写到editor中运行达到自行检测运行脚本方法顺序的目的)

    /*此类可以写在editor中运行达到自运行检测的目的*/
    public class MyInfoDebuger : MonoBehaviour {
        public GameObject SelectObj;
        /*目前只能读取脚本为 SelectObj中 TempReadJobScrpts的注释信息*/
        public readonly string TempReadJobScrpts= "TempReadJobScrpts";
        public bool IsReadBug = true;
        public bool ShowAllMehodOfScripts = false;
        // Use this for initialization
        void Start () {
            if (IsReadBug)
             ShowDebugInfo();
        }
        void GetAllMyPrivareScripts()
        {
            //获取所有自定义脚本的名字
        }
        public void ShowDebugInfo()
        {//这里需要修改成获取所有脚本的信息参数
            try
            {
                //仅在unity 中需要使用  此处非自执行。。便利脚本效率比较低
                //当方法加入public时 此处可以获取
                MonoBehaviour[] monos = SelectObj.GetComponents<MonoBehaviour>();
                foreach (var item in monos)
                {
                    if (item.GetType().ToString().EndsWith(TempReadJobScrpts))
                    {
                        Debug.Log("is reading>>:" + ((MonoBehaviour)item).GetType());
                        //显示有标签的方法 此处只能用在方法上    此处设置的是私有和共有方法
                        MethodInfo[] meths = ((MonoBehaviour)item).GetType().GetMethods(BindingFlags.Instance|BindingFlags.NonPublic|BindingFlags.Public);
                        foreach (MethodInfo met in meths)
                        {                        
                            if (Attribute.GetCustomAttributes(met).Length>0)
                            {
                                if (ShowAllMehodOfScripts)
                                    Debug.Log(met.Name);
    
                                Attribute[] attris = Attribute.GetCustomAttributes(met);                         
                                foreach (Attribute at in attris)
                                {
                                    if (at.GetType() == typeof(DebugerCoderAttribute))
                                    {
                                        DebugerCoderAttribute info = (DebugerCoderAttribute)at;
                                        Debug.Log("coder:" + info.ScriptsCoder + ","
                                            + " message:" + info.Message+" date:"+info.ScriptsTime);
                                    }
                                }
                            }
                        }
    
                    }
                }
            }
            catch (System.Exception ex)
            {
                Debug.Log(this.name+" "+ ex.ToString());
            }
    
        }
    }

     运行结构:

  • 相关阅读:
    Linux下安装配置SVN服务器,windows访问
    Zookeeper集群版搭建
    Zookeeper单机版启动
    Nginx-Session缓存一致性-memcached
    Nginx-配置多台Tomcat-反向代理
    Linux-tomcat-安装启动
    Linux-JDK-环境搭建安装
    Nginx-安装-运行访问页面
    Linux-虚拟机-克隆-学习
    解决CocosCreator 在微信小游戏中使用Socket.io 报错的问题
  • 原文地址:https://www.cnblogs.com/yangxiaohang/p/8018651.html
Copyright © 2011-2022 走看看