一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - ASP.NET教程 - ASP.Net Core中使用枚舉類而不是枚舉的方法

ASP.Net Core中使用枚舉類而不是枚舉的方法

2020-06-15 14:17菠蘿吹雪—Code ASP.NET教程

這篇文章主要給大家介紹了關(guān)于ASP.Net Core中使用枚舉類而不是枚舉的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用ASP.Net Core具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧

前言:

我相信大家在編寫代碼時經(jīng)常會遇到各種狀態(tài)值,而且為了避免硬編碼和代碼中出現(xiàn)魔法數(shù),通常我們都會定義一個枚舉,來表示各種狀態(tài)值,直到我看到Java中這樣使用枚舉,我再想C# 中可不可以這樣寫,今天就分享一下我的感悟。

一、通常我們是這樣使用枚舉的

(1)switch中使用枚舉

?
1
2
3
4
5
6
public enum EmployeeType
{
Manager,
Servant,
AssistantToTheRegionalManager
}
?
1
2
3
4
5
public class Employee
 {
 public EmployeeType Type { get; set; }
 public decimal Bonus { get; set; }
 }
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
static void ProcessBonus(Employee employee)
 {
  switch (employee.Type)
  {
  case EmployeeType.Manager:
   employee.Bonus = 1000m;
   break;
  case EmployeeType.Servant:
   employee.Bonus = 0.01m;
   break;
  case EmployeeType.AssistantToTheRegionalManager:
   employee.Bonus = 1.0m;
   break;
  default:
   throw new ArgumentOutOfRangeException();
  }
 }

在沒有進(jìn)某唐時我也是這樣的寫的,代碼很爛,違法了開閉原則,擴(kuò)展性極差。在代碼規(guī)范中是不允許出現(xiàn)這樣的寫法的。對于上面的寫法可以使用設(shè)計模式來重構(gòu)。后面會繼續(xù)更新設(shè)計模式的文章。

(2)類型轉(zhuǎn)換

?
1
2
EnumTricks.IsVolumeHigh((Volume)27);
EnumTricks.High((int)Medium);

二、枚舉的不好之處

關(guān)于枚舉的MSDN文檔說了什么:

“The enum keyword is used to declare an enumeration, a distinct type that consists of a set of named constants called the enumerator list. Every enumeration type has an underlying type, which can be any integral type except char. The default underlying type of the enumeration elements is int. By default, the first enumerator has the value 0, and the value of each successive enumerator is increased by 1.

(1)沒有類型安全

枚舉是簡單的值類型,可以提供對無效值的保護(hù),并且不會出現(xiàn)任何行為。他們是有用的,因為他們是魔法數(shù)字的改進(jìn),但就是這樣。如果要約束類型可能的值,枚舉不一定能幫助您,因為仍然可以提供無效類型。例如,此枚舉有三個值,默認(rèn)情況下將具有int類型。值范圍為1到3。

?
1
2
3
4
5
6
public enum Volume
{
Low = 1,
Medium,
High
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public static class EnumTricks
 {
 public static bool IsVolumeHigh(Volume volume)
 {
  var result = false;
 
  switch (volume)
  {
  case Volume.Low:
   Console.WriteLine("Volume is low.");
   break;
 
  case Volume.Medium:
   Console.WriteLine("Volume is medium.");
   break;
 
  case Volume.High:
   Console.WriteLine("Volume is high.");
   result = true;
   break;
  }
 
  return result;
 }
 }
?
1
2
3
4
5
6
7
8
static void Main(string[] args)
 {
  EnumTricks.IsVolumeHigh((Volume)27);
 
 
 
  Console.ReadKey();
 }
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
public static class EnumTricks
 {
 public static bool IsVolumeHigh(Volume volume)
 {
  var result = false;
 
  switch (volume)
  {
  case Volume.Low:
   Console.WriteLine("Volume is low.");
   break;
 
  case Volume.Medium:
   Console.WriteLine("Volume is medium.");
   break;
 
  case Volume.High:
   Console.WriteLine("Volume is high.");
   result = true;
   break;
  }
 
  return result;
 }
 
 public static int EnumToInt(Volume volume)
 {
  return (int)volume;
 }
 
 public static Volume IntToEnum(int intValue)
 {
  return (Volume)intValue;
 }
 
 public static Volume StringToEnum(string stringValue)
 {
  return (Volume)Enum.Parse(typeof(Volume), stringValue);
 }
 
 public static int StringToInt(string stringValue)
 {
  var volume = StringToEnum(stringValue);
  return EnumToInt(volume);
 }
 public static string EnumToString(Volume volume)
 {
  return volume.ToString();
 }
 }

這應(yīng)該失敗,至少在運(yùn)行時。它沒有。這真的很奇怪......在編譯期間或運(yùn)行期間都不會檢測到錯誤的調(diào)用。你會覺得自己處于一個虛假的安全狀態(tài)。如果,我們把傳進(jìn)去的枚舉轉(zhuǎn)換為string時,來看看這兩種情況有什么不同:

ASP.Net Core中使用枚舉類而不是枚舉的方法

我不知道大家平時在使用枚舉的時候,是否有意識檢查傳入的是否是有效的值。可以使用Enum.IsDefined()來檢查int值是否是一個有效的值

解決方案:如果int值在枚舉值的定義范圍內(nèi),則使用Enum.IsDefined()查找。如果在范圍內(nèi),則返回True,否則返回False。

(2)轉(zhuǎn)化

您是否嘗試過將enum轉(zhuǎn)換為int,int轉(zhuǎn)換為enum,string轉(zhuǎn)換為enum,將字符串轉(zhuǎn)換為enum的int值?如下代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public static class EnumTricks
 {
  public static bool IsVolumeHigh(Volume volume)
  {
   var result = false;
 
   switch (volume)
   {
    case Volume.Low:
     Console.WriteLine("Volume is low.");
     break;
 
    case Volume.Medium:
     Console.WriteLine("Volume is medium.");
     break;
 
    case Volume.High:
     Console.WriteLine("Volume is high.");
     result = true;
     break;
   }
 
   return result;
  }
 
  public static int EnumToInt(Volume volume)
  {
   return (int)volume;
  }
 
  public static Volume IntToEnum(int intValue)
  {
   return (Volume)intValue;
  }
 
  public static Volume StringToEnum(string stringValue)
  {
   return (Volume)Enum.Parse(typeof(Volume), stringValue);
  }
 
  public static int StringToInt(string stringValue)
  {
   var volume = StringToEnum(stringValue);
   return EnumToInt(volume);
  }
 }

是不是我們?nèi)粘5拇a中也有這樣的類型轉(zhuǎn)換代碼,不是說不好,只是類型轉(zhuǎn)換也是有性能損失的,如果能換中方式可以同樣實現(xiàn)而且還避免以上問題豈不是更好,這樣我們的代碼也更好維護(hù)和擴(kuò)展,下面我們通過使用枚舉類的方式來解決這個問題。

三、使用枚舉類而不是枚舉類型

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
public class Enumeration: IComparable
 {
  private readonly int _value;
  private readonly string _displayName;
 
  protected Enumeration()
  {
  }
 
  protected Enumeration(int value, string displayName)
  {
   _value = value;
   _displayName = displayName;
  }
 
  public int Value
  {
   get { return _value; }
  }
 
  public string DisplayName
  {
   get { return _displayName; }
  }
 
  public override string ToString()
  {
   return DisplayName;
  }
 
  public static IEnumerable<T> GetAll<T>() where T : Enumeration, new()
  {
   var type = typeof(T);
   var fields = type.GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly);
 
   foreach (var info in fields)
   {
    var instance = new T();
    var locatedValue = info.GetValue(instance) as T;
 
    if (locatedValue != null)
    {
     yield return locatedValue;
    }
   }
  }
 
  public override bool Equals(object obj)
  {
   var otherValue = obj as Enumeration;
 
   if (otherValue == null)
   {
    return false;
   }
 
   var typeMatches = GetType().Equals(obj.GetType());
   var valueMatches = _value.Equals(otherValue.Value);
 
   return typeMatches && valueMatches;
  }
 
  public override int GetHashCode()
  {
   return _value.GetHashCode();
  }
 
  public static int AbsoluteDifference(Enumeration firstValue, Enumeration secondValue)
  {
   var absoluteDifference = Math.Abs(firstValue.Value - secondValue.Value);
   return absoluteDifference;
  }
 
  public static T FromValue<T>(int value) where T : Enumeration, new()
  {
   var matchingItem = parse<T, int>(value, "value", item => item.Value == value);
   return matchingItem;
  }
 
  public static T FromDisplayName<T>(string displayName) where T : Enumeration, new()
  {
   var matchingItem = parse<T, string>(displayName, "display name", item => item.DisplayName == displayName);
   return matchingItem;
  }
 
  private static T parse<T, K>(K value, string description, Func<T, bool> predicate) where T : Enumeration, new()
  {
   var matchingItem = GetAll<T>().FirstOrDefault(predicate);
 
   if (matchingItem == null)
   {
    var message = string.Format("'{0}' is not a valid {1} in {2}", value, description, typeof(T));
    throw new ApplicationException(message);
   }
 
   return matchingItem;
  }
 
  public int CompareTo(object other)
  {
   return Value.CompareTo(((Enumeration)other).Value);
  }
 }
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public class Volume: Enumeration
 {
  private Volume() { throw new Exception(""); }
  private Volume(int value, string displayName): base(value, displayName) { }
 
 
  public static readonly Volume Low = new Volume(1, nameof(Low).ToLowerInvariant());
  public static readonly Volume Medium = new Volume(2, nameof(Medium).ToLowerInvariant());
  public static readonly Volume High = new Volume(3, nameof(High).ToLowerInvariant());
 
 
  public static IEnumerable<Volume> List() =>
   new[] { Low, Medium, High };
 
  public static Volume From(int value)
  {
   var state = List().SingleOrDefault(s => s.Value == value);
 
   if (state == null)
   {
    throw new Exception($"Possible values for Volume: {String.Join(",", List().Select(s => s.Value))}");
   }
 
   return state;
  }
 
  public static Volume FromName(string name)
  {
   var state = List()
    .SingleOrDefault(s => String.Equals(s.DisplayName, name, StringComparison.CurrentCultureIgnoreCase));
 
   if (state == null)
   {
    throw new Exception($"Possible values for Volume: {String.Join(",", List().Select(s => s.DisplayName))}");
   }
 
   return state;
  }
 }
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
static void Main(string[] args)
  {
   //EnumTricks.IsVolumeHigh((Volume)27);
 
   //var tmp = Enum.IsDefined(typeof(Volume), 3);
   //var str = EnumTricks.EnumToString((Volume)27);
   //var str2 = EnumTricks.EnumToString((Volume)3);
 
 
   //Console.WriteLine($"Volume 27:{str}");
   //Console.WriteLine($"Volume 3:{str2}");
 
   Console.WriteLine("------------------------------------------------------------");
   
   Console.WriteLine(Volume.High.Value);
   Console.WriteLine(Volume.High.DisplayName);
 
   var volume = Volume.From(2);
   var volume2 = Volume.FromName("high");
   var none = Volume.From(27);
 
   Console.ReadKey();
  }

四、應(yīng)用

ASP.Net Core中使用枚舉類而不是枚舉的方法

代碼如下:

Error文件下:

?
1
2
3
4
5
6
public interface ICommonError
 {
  int GetErrCode();
  string GetErrMsg();
  ICommonError SetErrMsg(string errMsg);
 }
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
public class Enumeration : IComparable
 {
  private readonly int _value;
  private readonly string _displayName;
 
  protected Enumeration()
  {
  }
 
  protected Enumeration(int value, string displayName)
  {
   _value = value;
   _displayName = displayName;
  }
 
  public int Value
  {
   get { return _value; }
  }
 
  public string DisplayName
  {
   get { return _displayName; }
  }
 
  public override string ToString()
  {
   return DisplayName;
  }
 
  public static IEnumerable<T> GetAll<T>() where T : Enumeration, new()
  {
   var type = typeof(T);
   var fields = type.GetFields(BindingFlags.Public | BindingFlags.Static | BindingFlags.DeclaredOnly);
 
   foreach (var info in fields)
   {
    var instance = new T();
    var locatedValue = info.GetValue(instance) as T;
 
    if (locatedValue != null)
    {
     yield return locatedValue;
    }
   }
  }
 
  public override bool Equals(object obj)
  {
   var otherValue = obj as Enumeration;
 
   if (otherValue == null)
   {
    return false;
   }
 
   var typeMatches = GetType().Equals(obj.GetType());
   var valueMatches = _value.Equals(otherValue.Value);
 
   return typeMatches && valueMatches;
  }
 
  public override int GetHashCode()
  {
   return _value.GetHashCode();
  }
 
  public static int AbsoluteDifference(Enumeration firstValue, Enumeration secondValue)
  {
   var absoluteDifference = Math.Abs(firstValue.Value - secondValue.Value);
   return absoluteDifference;
  }
 
  public static T FromValue<T>(int value) where T : Enumeration, new()
  {
   var matchingItem = parse<T, int>(value, "value", item => item.Value == value);
   return matchingItem;
  }
 
  public static T FromDisplayName<T>(string displayName) where T : Enumeration, new()
  {
   var matchingItem = parse<T, string>(displayName, "display name", item => item.DisplayName == displayName);
   return matchingItem;
  }
 
  private static T parse<T, K>(K value, string description, Func<T, bool> predicate) where T : Enumeration, new()
  {
   var matchingItem = GetAll<T>().FirstOrDefault(predicate);
 
   if (matchingItem == null)
   {
    var message = string.Format("'{0}' is not a valid {1} in {2}", value, description, typeof(T));
    throw new ApplicationException(message);
   }
 
   return matchingItem;
  }
 
  public int CompareTo(object other)
  {
   return Value.CompareTo(((Enumeration)other).Value);
  }
 }
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public class EmBusinessError : Enumeration, ICommonError
 {
  private int errCode;
  private String errMsg;
 
  public static readonly EmBusinessError parameterValidationError = new EmBusinessError(10001, "參數(shù)不合法");
 
  private EmBusinessError() { throw new Exception("私有構(gòu)造函數(shù)不能調(diào)用"); }
  private EmBusinessError(int value, string displayName) : base(value, displayName) {
 
   this.errCode = value;
   this.errMsg = displayName;
  }
  
  public int GetErrCode()
  {
   return this.errCode;
  }
 
  public string GetErrMsg()
  {
   return this.errMsg;
  }
 
  public void SetErrCode(int errCode)
  {
   this.errCode = errCode;
  }
 
  public ICommonError SetErrMsg(string errMsg)
  {
   this.errMsg = errMsg;
 
   return this;
  }
 }
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
//包裝器業(yè)務(wù)異常類實現(xiàn)
 public class BusinessException : Exception, ICommonError
 {
  private ICommonError commonError;
 
  //直接接收EmBusinessError的傳參用于構(gòu)造業(yè)務(wù)異常
  public BusinessException(ICommonError commonError):base()
  {
   this.commonError = commonError;
  }
  public BusinessException(ICommonError commonError, string errMsg):base()
  {
   this.commonError = commonError;
   this.commonError.SetErrMsg(errMsg);
  }
  public int GetErrCode()
  {
   return this.commonError.GetErrCode();
  }
 
  public string GetErrMsg()
  {
   return this.commonError.GetErrMsg();
  }
 
  public ICommonError SetErrMsg(string errMsg)
  {
   this.commonError.SetErrMsg(errMsg);
 
   return this;
  }
  public ICommonError GetCommonError()
  {
   return commonError;
  }
 }

異常中間件:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public class ExceptionHandlerMiddleWare
 {
  private readonly RequestDelegate next;
  
  /// <summary>
  ///
  /// </summary>
  /// <param name="next"></param>
  public ExceptionHandlerMiddleWare(RequestDelegate next)
  {
   this.next = next;
  }
 
  public async Task Invoke(HttpContext context)
  {
   try
   {
    await next(context);
   }
   catch (Exception ex)
   {
    await HandleExceptionAsync(context, ex);
   }
  }
 
  private static async Task HandleExceptionAsync(HttpContext context, Exception exception)
  {
   if (exception == null) return;
   await WriteExceptionAsync(context, exception).ConfigureAwait(false);
  }
 
  private static async Task WriteExceptionAsync(HttpContext context, Exception exception)
  {
   var response = context.Response;
   response.ContentType = "application/json;charset=utf-8";
   var result = new CommonReturnType();
   
 
   if (exception is BusinessException)
   {
    var businessException = (BusinessException)exception;
 
    var errModel = new { errCode= businessException.GetErrCode(), errMsg= businessException.GetErrMsg() };
 
    result = CommonReturnType.Create(errModel, "fail");
 
    
   }
   
 
   await response.WriteAsync(JsonConvert.SerializeObject(new { data = result.GetData(), status = result.GetStatus() }) ).ConfigureAwait(false);
  }
 
 }

Response文件夾:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public class CommonReturnType
 {
  //表明對應(yīng)請求的返回處理結(jié)果 "success" 或 "fail"
  private string status;
 
  //若status=success,則data內(nèi)返回前端需要的json數(shù)據(jù)
  //若status=fail,則data內(nèi)使用通用的錯誤碼格式
  private object data;
 
  //定義一個通用的創(chuàng)建方法
  public static CommonReturnType Create(object result)
  {
   return CommonReturnType.Create(result, "success");
  }
  
  public static CommonReturnType Create(object result, string status)
  {
   CommonReturnType type = new CommonReturnType();
   type.SetStatus(status);
   type.SetData(result);
 
   return type;
  }
 
  public string GetStatus()
  {
   return status;
  }
 
  public void SetStatus(string status)
  {
   this.status = status;
  }
 
  public object GetData()
  {
   return data;
  }
 
  public void SetData(object data)
  {
   this.data = data;
  }
 }

最后推薦一個類庫,這是我在Nuget上發(fā)現(xiàn)的枚舉類庫,地址:https://github.com/ardalis/SmartEnum

好了,先分享到這里,希望對你有幫助和啟發(fā)。

參考資料:

(1)https://docs.microsoft.com/zh-cn/dotnet/standard/microservices-architecture/microservice-ddd-cqrs-patterns/enumeration-classes-over-enum-types

(2)https://ardalis.com/enum-alternatives-in-c

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,謝謝大家對服務(wù)器之家的支持。

原文鏈接:https://www.cnblogs.com/runningsmallguo/p/10962414.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 午夜福利在线观看6080 | 久久精品中文騷妇女内射 | 狠狠色狠狠色综合婷婷tag | 精品国产福利一区二区在线 | 国产精品久热 | 日本xxxxx18护士xxx | 莫莉瑞典1977k | 亚洲国产精品久久久久 | 国产欧美日韩精品一区二 | www视频免费 | 欧美精品黑人巨大在线播放 | 亚洲男人的天堂成人 | 欧美日韩国产成人综合在线影院 | 国产欧美一区二区成人影院 | 69japanese日本100 6969精品视频在线观看 | 久久99r66热这里只有精品 | 成人性色生活片免费网 | 国产成人综合精品 | 国产激情久久久久影院小草 | 全色黄大色黄大片爽一次 | 成年视频在线观看免费 | 毛片免费毛片一级jjj毛片 | 亚洲va欧美va国产va天堂影 | 亚洲色图第四页 | 国产午夜视频在线观看网站 | 欧美在线看片a免费观看 | 赤坂丽女医bd无删减在线观看 | 好大好硬抽搐好爽想要 | 国产精品成人麻豆专区 | 国产精品一区二区久久 | 高中生放荡日记高h娜娜 | www.一区二区三区.com | 99久久国产综合精品女不卡 | 色婷婷综合和线在线 | 无删减影视免费观看 | 亚州精品视频 | 国产欧美视频在线观看 | 日本三级免费看 | 日本动漫xxxxxx| 午夜办公室在线观看高清电影 | 加勒比久草 |