<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      特性的學習

      特性

      在C#的編程過程之中,我們可以發現特性是無處不在的,那么什么是特性那?

      什么是特性?

      1. 特性其實就是一個類(class),聲明的時候,默認以Attribute結尾,直接或者間接的繼承Attribute抽象類。
      2. 當我們應用特性的時候,是把這個特性以[]包裹標記在類或者類內部成員上。

      特性和注釋的區別?

      1. 注釋只是一個描述;在編譯后,是不存在的。
      2. 特性

      如何自定義特性,特性的多種標記

      1. 標記的是,如果是以Attribute結尾,Attribute可以省略掉,直接或間接繼承Attribute。
      2. 可以標記類的內部的任何成員上。
      3. 特性在標記的時候,其實就是調用構造函數。
      4. 在標記的時候也可以對公開的屬性或字段賦值
      5. 默認是不能重復標記的
      6. AttributeUsage:也是一個特性,是用來修飾特性的特性
      7. AttributeTargets指定當前特性只能標記到某個地方:建議大家在自己定義特性的時候,最好能夠明確指定AttributeTargets--明確告訴別人,我這個特性是專門用來標記在哪里的。
      8. AllowMultiple:是否可以重復標記。
      9. Inherited:是否可以繼承特性
        定義一個特性:
      [AttributeUsage(AttributeTargets.All,AllowMultiple =true,Inherited =true)]
      public class CustomAttribute : Attribute
      { 
          private int _Id { get; set; } 
          public string _Name { get; set; } 
      
          public int _Age;
      
          //public CustomAttribute()
          //{
          //}
      
          public CustomAttribute(int id)
          {
              this._Id = id;
          }
      
          public CustomAttribute(string name)
          {
              this._Name = name;
          }
      
          public void Do()
          {
              Console.WriteLine("this is  CustomAttribute");
          }
      }
      
      

      如何調用到特性內部的成員--自定義的這個特性,如何才能使用它那?

      1. 進入反編譯以后,在標記有特性的類的內部,生成了custom的成員,但是我們不能直接調用;--要通過反射調用。要讓特性生效,實際上來說就是要去執行我們這個特性?--就需要構造特性的實例。
      2. 在使用反射獲取特性的時候,可以把標記在任何地方的特性都可以獲取到
      3. 既然標記的特性可以通過反射來獲取到實例,就可以加以應用
        code:
      public class InvokeAttributeManager
      {
          /// <summary>
          /// 通過反射來調用特性---確實是可以調用到特性的實例的
          /// </summary>
          /// <typeparam name="T"></typeparam>
          /// <param name="t"></param>
          public static void Show(Student student)
          {
              //Type type = typeof(Student);
              Type type = student.GetType(); 
              //1.先判斷是否有特性
              if (type.IsDefined(typeof(CustomAttribute), true))
              { 
                  //2.獲取--先判斷再獲取--為了提高性能
                  foreach (CustomAttribute attribute in type.GetCustomAttributes(true))
                  {
                      Console.WriteLine($"attribute._Name:{attribute._Name}");
                      Console.WriteLine($"attribute._Age:{attribute._Age}"); 
                      attribute.Do();
                  }
              }
      
              //獲取當前Type下所有的屬性上標記的特性
              foreach (PropertyInfo prop in type.GetProperties())
              {
                  if (prop.IsDefined(typeof(CustomAttribute), true))
                  {
                      //2.獲取--先判斷再獲取--為了提高性能
                      foreach (CustomAttribute attribute in prop.GetCustomAttributes(true))
                      {
                          Console.WriteLine($"attribute._Name:{attribute._Name}");
                          Console.WriteLine($"attribute._Age:{attribute._Age}");
                          attribute.Do();
                      }
                  }
              }
      
              //獲取當前Type下所有的字段上標記的特性
              foreach (FieldInfo field in type.GetFields())
              {
                  if (field.IsDefined(typeof(CustomAttribute), true))
                  {
                      //2.獲取--先判斷再獲取--為了提高性能
                      foreach (CustomAttribute attribute in field.GetCustomAttributes(true))
                      {
                          Console.WriteLine($"attribute._Name:{attribute._Name}");
                          Console.WriteLine($"attribute._Age:{attribute._Age}");
                          attribute.Do();
                      }
                  }
              }
      
              //獲取當前Type下所有的方法上標記的特性
              foreach (MethodInfo method in type.GetMethods())
              {
                  foreach (ParameterInfo para in method.GetParameters())
                  {
                      if (para.IsDefined(typeof(CustomAttribute), true))
                      {
                          //2.獲取--先判斷再獲取--為了提高性能
                          foreach (CustomAttribute attribute in para.GetCustomAttributes(true))
                          {
                              Console.WriteLine($"attribute._Name:{attribute._Name}");
                              Console.WriteLine($"attribute._Age:{attribute._Age}");
                              attribute.Do();
                          }
                      }
                  }
      
      
                  if (method.IsDefined(typeof(CustomAttribute), true))
                  {
                      //2.獲取--先判斷再獲取--為了提高性能
                      foreach (CustomAttribute attribute in method.GetCustomAttributes(true))
                      {
                          Console.WriteLine($"attribute._Name:{attribute._Name}");
                          Console.WriteLine($"attribute._Age:{attribute._Age}");
                          attribute.Do();
                      }
                  }
              }
      
      
      
          }
      }
      

      特性獲取額外信息

      一、傳統方式獲取枚舉
      我們會實現這樣的一個需求,比方有一個用戶信息,用戶信息中有一個狀態字段;在數據庫中保存數據的時候,保存的是1,2,3 對應的就是這個枚舉;數據庫中保存的是數字,但是我們在查詢到數據以后,展示給界面的時候,就可以通過特性來實現。

          public enum UserStateEnum
          {
              Normal = 1,
              Frozen = 2,
              Deleted = 3
          }
      

      面對上述的情況,我們往往需要通過分支判斷來判斷狀態,在面對描述信息改了?我們就需要每一個使用此枚舉的地方,導致工作量的增加。
      二、通過特性來獲取特性信息---額外信息---特性獲取額外信息
      定義一個特性類

          [AttributeUsage(AttributeTargets.Field)]
          public class RemarkAttribute:Attribute
          {
              private string _Desc;
              public RemarkAttribute(string desc)
              {
                  _Desc = desc;
              }
              public string GetRemark()
              {
                  return this._Desc;
                 
              }
          }
      }
      

      調用特性方法

      public  class RemarkAttributeExtension
      {
          public static string GetRemark(UserStateEnum userState)
          {
              Type type = userState.GetType();
              string fieldName = userState.ToString();
              FieldInfo? fieldInfo = type.GetField(fieldName);
              if (fieldInfo.IsDefined(typeof(RemarkAttribute), true))
              {
      
                  RemarkAttribute attribute =fieldInfo.GetCustomAttribute<RemarkAttribute>();
                  return attribute.GetRemark();
              }
      
              return userState.ToString();
          }
           
      }
      

      好處:

      1. 如果增加了新的字段,就可以直接獲取不用其他改動
      2. 描述修改后,獲取描述信息的方法不用修改
        這樣我們還可以更改我們的RemarkAttributeExtension類變成擴展方法
       public static  class RemarkAttributeExtension
       {
           public static string GetRemark(this Enum @enum)
           {
               Type type = @enum.GetType();
               string fieldName = @enum.ToString();
               FieldInfo? fieldInfo = type.GetField(fieldName);
               if (fieldInfo.IsDefined(typeof(RemarkAttribute), true))
               {
      
                   RemarkAttribute attribute =fieldInfo.GetCustomAttribute<RemarkAttribute>();
                   return attribute.GetRemark();
               }
      
               return @enum.ToString();
           }
            
       }
      

      更改我們的代碼為;

          UserStateEnum Normal = UserStateEnum.Normal;
          UserStateEnum Frozen = UserStateEnum.Frozen;
          UserStateEnum Deleted = UserStateEnum.Deleted;
      
          Console.WriteLine(RemarkAttributeExtension.GetRemark(Normal));
          Console.WriteLine(RemarkAttributeExtension.GetRemark(Frozen));
          Console.WriteLine(RemarkAttributeExtension.GetRemark(Deleted));
      
          Console.WriteLine(Normal.GetRemark());
          Console.WriteLine(Frozen.GetRemark());
          Console.WriteLine(Deleted.GetRemark());
      
      

      這樣我們通過反射+特性+擴展方法,可以封裝一個獲取額外新的公共方法。

      特性獲取額外功能

      添加一個功能

      1. 如果要保存一條數據到數據庫中去
      2. 從前端提交過來的數據格式為:
        {
        "id":0,
        "name":"string",
        "age":0
        "state":1
        }
        3.包含了很多字;
        4.如果數據庫總Name的值要求存儲的長度為40個字符---如果保存的數據超過40個字符---肯定會報錯
      3. 肯定要在保存之前就是需要驗證這行數據。
        我們先驗證我們的用戶名不能為空的一個驗證:
      
       [AttributeUsage(AttributeTargets.Property)]
       public class Required:Attribute
       {
           public string _ErrorMessage;
           public Required(string message) {
               this._ErrorMessage = message;   
           }
           public bool Validate(object value)
           {
      
               bool bResult = value != null && !string.IsNullOrWhiteSpace(value.ToString());
               return bResult;
           }
       }
      
      

      之后,就是我們調用特性的代碼

      public class ValidateInvokeManager
      {
          public static bool Validate<T>(T t) where T : class
          {
              Type type = typeof(T);
              foreach (var prop in type.GetProperties())
              {
                  if (prop.IsDefined(typeof(Required),true))
                  {
                      Required required = prop.GetCustomAttribute<Required>();
                      if (required.Validate(prop.GetValue(t))==false)
                      {
                          return false;
                      }
                  }
              }
              return true;
          }
      }
      

      在這里,只是添加一個用戶名非空的一個驗證,下面是我們的用戶類

           public int Id { get; set; }
           [Required("不能為空")]
           public string Name { get; set; }
           public int Age { get; set; }
           public long QQ { get; set; }
      
           public string Mobile { get; set; }
           public UserStateEnum UserState { get; set; }
      
      

      這里我們再添加一個長度的限制

      public class LengthAttribute : Attribute
      {
          public string _ErrorMessage;
          private int _Min;
          private int _Max;
      
      
          public LengthAttribute(int min, int max)
          {
              this._Min = min;
              this._Max = max;
          }
          public bool Validate(object value)
          {
              if (value != null)
              {
                  if (value.ToString().Length < _Min || value.ToString().Length > _Max)
                  {
                      return false;
                  }
                  else
                  {
                      if (value.ToString().Length == 0)
                      {
                          return false;
                      }
                      else
                      {
                          return true;
                      }
      
                  }
              }
              return false;
      
          }
      }
      

      對應的用戶類:

      public class UserInfo
      {
          public int Id { get; set; }
      
          [Required("Name的值不能為空")]
          public string Name { get; set; }
      
          public int Age { get; set; }
      
          public long QQ { get; set; }
      
          
          [Required("Mobile的值不能為空")]
          [Length(11, 11, _ErrorMessage = "手機號必須為11位數")]
          public string Mobile { get; set; }
      
          public UserStateEnum State { get; set; }
      
          public string UserStateDescription
          {
              get
              {
                  return this.State.GetRemark();
              }
          }
      }
      

      這樣其實并不是很通用,我們再去更改一個通用的版本。
      定義一個抽象的類

      
          public abstract class AbstractAttribute : Attribute
          {
              public abstract bool Validate(object oValue);
          }
      }
      

      改造一下我們對應的驗證的類

        [AttributeUsage(AttributeTargets.Property)]
        public class Required: AbstractAttribute
        {
            public string _ErrorMessage;
            public Required(string message) {
                this._ErrorMessage = message;   
            }
            public override bool Validate(object value)
            {
      
                bool bResult = value != null && !string.IsNullOrWhiteSpace(value.ToString());
                return bResult;
            }
        }
      
       public class LengthAttribute : AbstractAttribute
       {
           public string _ErrorMessage;
           private int _Min;
           private int _Max;
      
      
           public LengthAttribute(int min, int max)
           {
               this._Min = min;
               this._Max = max;
           }
           public override bool Validate(object value)
           {
               if (value != null)
               {
                   if (value.ToString().Length < _Min || value.ToString().Length > _Max)
                   {
                       return false;
                   }
                   else
                   {
                       if (value.ToString().Length == 0)
                       {
                           return false;
                       }
                       else
                       {
                           return true;
                       }
      
                   }
               }
               return false;
      
           }
       }
      
      

      對應的驗證類

        public static bool Validate<T>(T t) where T : class
        {
            Type type = typeof(T);
            foreach (var prop in type.GetProperties())
            {
                if (prop.IsDefined(typeof(AbstractAttribute), true))
                {
                    object oValue = prop.GetValue(t);
                    foreach (AbstractAttribute attribute in prop.GetCustomAttributes())
                    {
                        bool apiResult = attribute.Validate(oValue);
                        if (apiResult == false)
                        {
                            return apiResult;
                        }
                    }
                }
            }
      
            return true;
        }
      

      這樣我們又遇到了一個問題,什么問題?我們僅僅是知道了我們驗證失敗了,但是因為什么才導致我們的驗證失敗的信息還不清楚。
      我們開始引入ApiResult這個類,來解決這個問題.

          public class ApiResult
      {
          public bool ret { get; set; }
          public string _ErrorMessage { get; set; }
      }
      

      對應的驗證類:

         public class LengthAttribute : AbstractAttribute
         {
             public string _ErrorMessage;
             private int _Min;
             private int _Max;
      
      
             public LengthAttribute(int min, int max)
             {
                 this._Min = min;
                 this._Max = max;
             }
             public override ApiResult Validate(object value)
             {
                 if (value != null)
                 {
                     if (value.ToString().Length < _Min || value.ToString().Length > _Max)
                     {
      
                         return new ApiResult() { ret = false, _ErrorMessage = this._ErrorMessage };
                     }
                     else
                     {
                         if (value.ToString().Length == 0)
                         {
      
                             return new ApiResult() { ret = false, _ErrorMessage = this._ErrorMessage };
                         }
                         else
                         {
      
                             return new ApiResult() { ret = true, _ErrorMessage =null};
                         }
      
                     }
                 }
                 return new ApiResult() { ret = true, _ErrorMessage = null }; 
      
             }
         }
      
       public class RequiredAttribute : AbstractAttribute
       {
           public string _ErrorMessage;
           public RequiredAttribute(string message) {
               this._ErrorMessage = message;   
           }
           public override ApiResult Validate(object value)
           {
      
               bool bResult = value != null && !string.IsNullOrWhiteSpace(value.ToString());
               if (bResult)
               {
                   return new ApiResult()
                   {
                       ret = bResult
                   };
               }
               else
               {
                   return new ApiResult()
                   {
                       ret = bResult,
                       _ErrorMessage = _ErrorMessage
                   };
               }
      
           }
       }
      

      調用特性的類

      
       public static ApiResult Validate<T>(T t) where T : class
       {
           Type type = typeof(T);
           foreach (var prop in type.GetProperties())
           {
               if (prop.IsDefined(typeof(AbstractAttribute), true))
               {
                   object oValue = prop.GetValue(t);
                   foreach (AbstractAttribute attribute in prop.GetCustomAttributes())
                   {
                       ApiResult apiResult = attribute.Validate(oValue);
                       if (apiResult.ret == false)
                       {
                           return apiResult;
                       }
                   }
               }
           }
      
           return new ApiResult { ret = true, _ErrorMessage = null };
       }
      

      運行的結果:

      好處:
      1.只要是把驗證的規則特性定義好,就可以重新使用
      2.如果需要驗證哪個屬性,就把特性標記在哪個屬性上就可以了;
      3.只是標記了一個特性,就可以獲取了一個驗證的邏輯。

      這樣就完成了特性添加額外信息和特性添加額外功能的作用。

      posted @ 2023-12-15 16:02  飄雨的河  閱讀(58)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 日韩中文字幕精品人妻| 国产成人免费观看在线视频| 五华县| 加勒比无码人妻东京热| 久热这里有精彩视频免费| 亚洲av无码牛牛影视在线二区| 精品无码国产日韩制服丝袜| 甘肃省| 五月综合激情婷婷六月| 亚洲色婷婷婷婷五月基地| 久久人人97超碰精品| 日韩视频一区二区三区视频| 国产美女69视频免费观看| 日韩一卡二卡三卡四卡五卡| 青草99在线免费观看| 国产成人精品18| 国自产拍偷拍精品啪啪一区二区| 色综合天天综合网天天看片| 成人免费无遮挡在线播放| 精品偷拍一区二区三区| 久久香蕉国产线看观看怡红院妓院| 无码专区 人妻系列 在线| 人妻中文字幕av资源站| 久久精品人人做人人爽97| 精品国产成人国产在线视| 无码国产精品一区二区免费虚拟vr | av午夜福利一片看久久| 日韩欧美视频一区二区三区| h无码精品动漫在线观看| 全国最大成人网| 99精品国产一区在线看| 中文精品无码中文字幕无码专区| 国产精品自在线拍国产| 中文字幕国产精品一二区| 中文字幕亚洲综合第一页| 国产h视频在线观看| 孝昌县| jizz视频在线观看| 久久99精品国产99久久6尤物| 无码国产69精品久久久久网站| 亚洲乱色一区二区三区丝袜|