C# 實體更新記錄:如何捕獲和記錄字段變化到日志

方案一:粗糙但可用
?

var changes = new List<string>();void CompareAndAddChange<T>(string propertyName, T oldValue, T newValue, Func<T, string> descriptionFunc = null)
{if (!EqualityComparer<T>.Default.Equals(oldValue, newValue)){var oldValueStr = descriptionFunc != null ? descriptionFunc(oldValue) : oldValue.ToString();var newValueStr = descriptionFunc != null ? descriptionFunc(newValue) : newValue.ToString();changes.Add($"{propertyName}: [{oldValueStr}] => [{newValueStr}]");}
}CompareAndAddChange("公司名稱", cusOld.CompanyName, modelDto.CompanyName);
CompareAndAddChange("公司類型", cusOld.CompanyType, modelDto.CompanyType, x => x.GetDescription());
CompareAndAddChange("公司代碼", cusOld.CompanyCode, modelDto.CompanyCode);
CompareAndAddChange("公司介紹", cusOld.Contents, modelDto.Contents);
CompareAndAddChange("會員等級", cusOld.MemberLevel, modelDto.MemberLevel, x => x.GetDescription());
CompareAndAddChange("會員類型", cusOld.MemberType, modelDto.MemberType, x => x.GetDescription());
CompareAndAddChange("業務員", cusOld.SaleId, modelDto.SaleId, async id =>
{var user = await _userRepository.GetWhereAsync(x => x.Id == id);return user?.NickName ?? id.ToString();
});
CompareAndAddChange("點數", cusOld.Ratio, modelDto.Ratio);
CompareAndAddChange("聯系方式", cusOld.Phone, modelDto.Phone);
CompareAndAddChange("會員有效期", cusOld.MemberValidityPeriod, modelDto.MemberValidityPeriod);
CompareAndAddChange("最大API客戶數", cusOld.MaxApiCusCount, modelDto.MaxApiCusCount);
CompareAndAddChange("最大渠道數", cusOld.MaxChannelCount, modelDto.MaxChannelCount);
CompareAndAddChange("最大供應商數", cusOld.MaxSupplierCount, modelDto.MaxSupplierCount);
CompareAndAddChange("備注", cusOld.Remark, modelDto.Remark);var content = string.Join(",", changes);

這種優化方式做了以下改進:

  1. 單一函數處理比較和改變的添加:使用泛型方法 CompareAndAddChange 來處理每個屬性的比較和變更添加,避免了重復的邏輯。

  2. 異步處理:在需要獲取業務員信息時,通過異步方法從 _userRepository 中獲取用戶信息。

  3. 描述函數:對于特定屬性(如枚舉類型),提供了描述函數,用于獲取更具描述性的字符串,提高了可讀性。

這種方法不僅減少了代碼量,還提高了可維護性和可擴展性,使得未來對屬性的改動更易于處理和擴展。


方案二:優化更舒服、反射

var changes = new List<string>();// 獲取所有屬性
var properties = typeof(ModelDto).GetProperties();foreach (var property in properties)
{// 獲取屬性值var oldValue = property.GetValue(cusOld);var newValue = property.GetValue(modelDto);// 如果新舊值不相等if (!Equals(oldValue, newValue)){// 特殊處理 SaleId 屬性if (property.Name == "SaleId"){var userNew = await _userRepository.GetWhereAsync(x => x.Id == (int)newValue);var userOld = await _userRepository.GetWhereAsync(x => x.Id == (int)oldValue);changes.Add($"業務員: [{userOld?.NickName}] => [{userNew?.NickName}]");}else{changes.Add($"{property.Name}: [{oldValue}] => [{newValue}]");}}
}var content = string.Join(",", changes);

這種方法的優點包括:

  1. 自動化屬性比較:利用反射獲取 ModelDto 的所有屬性,并比較舊值和新值。

  2. 特殊處理:對于特定屬性(如 SaleId),可以根據需要進行特殊處理,例如異步獲取用戶信息。

  3. 簡化代碼:避免了手動編寫每個屬性的比較邏輯,使代碼更加簡潔和易于維護。

  4. 可擴展性:如果需要比較的屬性增加或者需要額外的特殊處理,只需在相應的位置添加邏輯即可。

這種方法適合于需要自動化處理屬性比較和生成變更日志的場景,能夠有效地提高代碼的復用性和可維護性。

方案三:進階加描述

如果你想要在使用反射時獲取屬性的自定義備注或描述,你可以借助 C# 中的自定義屬性來實現。以下是一個簡單的示例,展示如何定義一個自定義屬性,并在反射時使用它獲取字段的備注:

首先,定義一個自定義屬性類 FieldDescriptionAttribute

[AttributeUsage(AttributeTargets.Property)]
public class FieldDescriptionAttribute : Attribute
{public string Description { get; }public FieldDescriptionAttribute(string description){Description = description;}
}

然后,在你的 ModelDto 類中使用這個自定義屬性:

public class ModelDto
{[FieldDescription("公司名稱")]public string CompanyName { get; set; }[FieldDescription("公司類型")]public CompanyType CompanyType { get; set; }[FieldDescription("公司代碼")]public string CompanyCode { get; set; }// 其他屬性省略
}

接下來,在生成變更內容時,使用這些自定義屬性來獲取字段的備注:

var changes = new List<string>();var properties = typeof(ModelDto).GetProperties();foreach (var property in properties)
{var oldValue = property.GetValue(cusOld);var newValue = property.GetValue(modelDto);if (!Equals(oldValue, newValue)){// 獲取屬性上的 FieldDescriptionAttributevar descriptionAttribute = (FieldDescriptionAttribute)property.GetCustomAttributes(typeof(FieldDescriptionAttribute), false).FirstOrDefault();// 如果找到了 FieldDescriptionAttribute,則使用其描述,否則使用屬性名var propertyName = descriptionAttribute != null ? descriptionAttribute.Description : property.Name;// 特殊處理 SaleId 屬性if (property.Name == "SaleId"){var userNew = await _userRepository.GetWhereAsync(x => x.Id == (int)newValue);var userOld = await _userRepository.GetWhereAsync(x => x.Id == (int)oldValue);changes.Add($"{propertyName}: [{userOld?.NickName}] => [{userNew?.NickName}]");}else{changes.Add($"{propertyName}: [{oldValue}] => [{newValue}]");}}
}var content = string.Join(",", changes);

在上面的示例中,FieldDescriptionAttribute 允許你為每個屬性指定一個自定義的描述。在遍歷屬性時,使用 GetCustomAttributes 方法獲取屬性上的自定義屬性,并從中獲取描述信息,以替代默認的屬性名作為變更內容的一部分。

這種方法能夠使你的代碼更具可讀性和可維護性,特別是在處理需要詳細描述的屬性時。

方案四:獲取summary備注

/// <summary>
/// 備注
/// </summary>

如果你希望在生成變更內容時,使用屬性的 XML 注釋(summary),或者自定義的備注信息作為字段的描述,可以結合使用反射和 XML 注釋讀取來實現。以下是一個示例:

首先,假設你的 ModelDto 類定義如下:

public class ModelDto
{/// <summary>/// 公司名稱/// </summary>public string CompanyName { get; set; }/// <summary>/// 公司類型/// </summary>public CompanyType CompanyType { get; set; }/// <summary>/// 公司代碼/// </summary>public string CompanyCode { get; set; }// 其他屬性省略
}

然后,可以編寫一個方法來獲取屬性的備注信息,優先使用 XML 注釋(summary),如果沒有 XML 注釋則使用自定義的備注信息:

public static string GetPropertyDescription(PropertyInfo property)
{// 嘗試獲取 XML 注釋(summary)var xmlComment = property.GetCustomAttributes(typeof(System.ComponentModel.DescriptionAttribute), false).FirstOrDefault() as System.ComponentModel.DescriptionAttribute;if (xmlComment != null){return xmlComment.Description;}// 如果沒有 XML 注釋,則使用屬性名作為備注return property.Name;
}

最后,根據這個方法來生成變更內容:

var changes = new List<string>();var properties = typeof(ModelDto).GetProperties();foreach (var property in properties)
{var oldValue = property.GetValue(cusOld);var newValue = property.GetValue(modelDto);if (!Equals(oldValue, newValue)){var propertyName = GetPropertyDescription(property);// 特殊處理 SaleId 屬性if (property.Name == "SaleId"){var userNew = await _userRepository.GetWhereAsync(x => x.Id == (int)newValue);var userOld = await _userRepository.GetWhereAsync(x => x.Id == (int)oldValue);changes.Add($"{propertyName}: [{userOld?.NickName}] => [{userNew?.NickName}]");}else{changes.Add($"{propertyName}: [{oldValue}] => [{newValue}]");}}
}var content = string.Join(",", changes);

在上面的示例中,GetPropertyDescription 方法會嘗試從 XML 注釋(summary)中獲取屬性的描述信息,如果找不到 XML 注釋,則默認使用屬性的名稱。這樣可以根據屬性的描述信息生成更具描述性的變更內容。

這種方法結合了反射和 XML 注釋讀取,能夠使你的代碼更加靈活和可維護,特別是在需要生成詳細變更日志或報告時非常有用。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/46103.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/46103.shtml
英文地址,請注明出處:http://en.pswp.cn/web/46103.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

分支定界法(Branch and Bound, 簡稱BB)是一種求解整數規劃問題的有效算法。

分支定界法&#xff08;Branch and Bound&#xff09;詳解與Python代碼示例 分支定界法概述 分支定界法&#xff08;Branch and Bound, 簡稱B&B&#xff09;是一種求解整數規劃問題的有效算法。它結合了搜索與迭代的思想&#xff0c;通過系統地枚舉候選解來尋找最優解。在…

Java Web常見框架尋找路由技巧

在Java Web代碼審計中&#xff0c;尋找和識別路由是很關鍵的部分。通過注冊的路由可以找到當前應用對應的Controller&#xff0c;其作為MVC架構中的一個組件&#xff0c;可以說是每個用戶交互的入口點。簡單介紹下Java Web中常見框架&#xff08;Spring Web、Jersey&#xff09…

【SASS/SCSS(二)】模塊化語法

目錄 一、use 1、命名空間 2、私有變量 3、用with改變模塊中的默認值 二、forward 1、給forward模塊起別名&#xff0c;讓成員加前綴 2、利用hide or show手動控制成員的可訪問性 三、import 1、不存在命名空間&#xff0c;成員變量在import之后直接公開 2、可以在嵌…

springboot防止重復提交的方案有哪些

在Spring Boot中&#xff0c;防止接口或表單重復提交有多種策略&#xff0c;以下是幾種常見且有效的方案&#xff1a; 前端控制&#xff1a; 禁用提交按鈕&#xff1a;在表單提交后&#xff0c;使用JavaScript立即禁用提交按鈕&#xff0c;防止用戶再次點擊。響應式提示&#x…

十、Java集合 ★ ?(模塊18-20)【泛型、通配符、List、Set、TreeSet、自然排序和比較器排序、Collections、可變參數、Map】

day05 泛型,數據結構,List,Set 今日目標 泛型使用 數據結構 List Set 1 泛型 1.1 泛型的介紹 ★ 泛型是一種類型參數&#xff0c;專門用來保存類型用的 最早接觸泛型是在ArrayList&#xff0c;這個E就是所謂的泛型了。使用ArrayList時&#xff0c;只要給E指定某一個類型…

講真,現在留給2024年下半年軟考的時間還夠嗎?

常識是個好東西&#xff0c;但是有時候卻容易蒙蔽咱們的雙眼&#xff0c;就拿下半年軟考而言&#xff0c;看起來現在才7月份&#xff0c;剛剛入伏&#xff0c;考試要到11月份&#xff0c;是冬天呢&#xff0c;中間還隔了一個完整的秋季&#xff0c;常識感覺還很遙遠&#xff0c…

【Vue3】4個比較重要的設計模式!!

大家好,我是CodeQi! 一位熱衷于技術分享的碼仔。 在我投身于前端開發的職業生涯期間,曾有一次承接了一個大型項目的維護工作。此項目運用的是 Vue 框架,然而其代碼結構紊亂不堪,可維護性極度糟糕??。 這使我深刻領會到,理解并運用 Vue 中的重要設計模式是何等關鍵! …

對LinkedList ,單鏈表和雙鏈表的理解

一.ArrayList的缺陷 二.鏈表 三.鏈表部分相關oj面試題 四.LinkedList的模擬實現 五.LinkedList的使用 六.ArrayList和LinkedList的區別 一.ArrayList的缺陷: 1. ArrayList底層使用 數組 來存儲元素&#xff0c;如果不熟悉可以來再看看&#xff1a; ArrayList與順序表-CSDN…

一些常見的網絡故障

&#x1f4d1;打牌 &#xff1a; da pai ge的個人主頁 &#x1f324;?個人專欄 &#xff1a; da pai ge的博客專欄 ??寶劍鋒從磨礪出&#xff0c;梅花香自苦寒來 ??運維工程師的職責&#xff1a;監…

【數據分析】Python數據分析實戰:從零開始構建數據管道

Python數據分析實戰&#xff1a;從零開始構建數據管道 引言一、數據獲取二、數據清洗三、數據分析四、數據可視化五、案例研究&#xff1a;預測股票價格結論 我嘗試訪問您所提供的鏈接&#xff0c;但似乎該鏈接指向的內容已失效或被移除&#xff0c;因此無法直接獲取并閱讀該文…

【iOS】——ARC源碼探究

一、ARC介紹 ARC的全稱Auto Reference Counting. 也就是自動引用計數。使用MRC時開發者不得不花大量的時間在內存管理上&#xff0c;并且容易出現內存泄漏或者release一個已被釋放的對象&#xff0c;導致crash。后來&#xff0c;Apple引入了ARC。使用ARC&#xff0c;開發者不再…

BUUCTF逆向wp [HDCTF2019]Maze

第一步 查殼&#xff0c;本題是32位&#xff0c;有殼&#xff0c;進行脫殼。 第二步 這里的 jnz 指令會實現一個跳轉&#xff0c;并且下面的0EC85D78Bh被標紅了&#xff0c;應該是一個不存在的地址&#xff0c;這些東西就會導致IDA無法正常反匯編出原始代碼&#xff0c;也稱…

中文科技核心論文發表

中文科技核心論文題目如下&#xff1a; 1.混凝土結構用纖維增強塑料筋的耐久性評述&#xff1a;適合建筑、結構、材料等專業 2.建筑工程用阻燃塑料的研究進展&#xff1a;適合建筑、材料專業 3.纖維增強熱塑性塑料在面部護具中的應用研究&#xff1a;適合化工、醫學、材料等專…

springcloud2021.x使用nacos做配置中心

spirngcloud2021.0.5使用nacos做配置中心遇到的問題 環境 jdk1.8&#xff0c;spring-boot 2.6.13&#xff0c;spring-cloud-alibaba 2021.0.5.0 &#xff0c;spring-cloud 2021.0.5 方案一 application.properties # Nacos幫助文檔: https://nacos.io/zh-cn/docs/concepts…

C++中的condition_variable:條件變量

理解 C 中的條件變量&#xff08;Condition Variable&#xff09; 在多線程編程中&#xff0c;我們常常需要一個線程等待某個條件的變化&#xff0c;比如等待數據的生成或某個標志位的設置。如果沒有條件變量&#xff08;condition_variable&#xff09;&#xff0c;線程可能會…

啟智暢想火車類集裝箱號碼識別技術,軟硬件解決方案

集裝箱號碼識別需求&#xff1a; 實時檢測車皮號、火車底盤號碼、集裝箱號碼&#xff0c;根據火車類型分為以下三種情況&#xff1a; 1、純車皮&#xff0c;只檢測車皮號&#xff1b; 2、火車拉貨箱&#xff08;半車皮&#xff09;&#xff0c;檢測車皮號集裝箱號碼&#xff1b…

如何從0搭建一個Ai智體day01

&#x1f4da;《AI破局行動&#xff5c;AI智能體&#xff08;coze&#xff09;實戰手冊》&#xff1a; https://d16rg8unadx.feishu.cn/wiki/XQESwHW5HiPFlrkZbkqc0Xp7nEb 說明 這個是授權訪問的&#xff0c;想學習加我 微信/ Github:** watchpoints &#x1f4fa;Day1-大圣直播…

玩轉HarmonyOS NEXT之常用布局三

輪播&#xff08;Swiper&#xff09; Swiper組件提供滑動輪播顯示的能力。Swiper本身是一個容器組件&#xff0c;當設置了多個子組件后&#xff0c;可以對這些子組件進行輪播顯示。通常&#xff0c;在一些應用首頁顯示推薦的內容時&#xff0c;需要用到輪播顯示的能力。 針對…

git開發流程

分支介紹 master - 主分支 所有提供給用戶使用的正式版本&#xff0c;都在這個主分支上發布 開發者在此分支 不可進行 push 操作 dev - 開發分支 日常開發所使用的分支&#xff0c;開發者完成的階段性功能模塊將首先被合并到此分支 此分支亦是團隊內部測試、階段性工作驗證…

Xcode 16 beta3 真機調試找不到 Apple Watch 的嘗試解決

很多小伙伴們想用 Xcode 在 Apple Watch 真機上調試運行 App 時卻發現&#xff1a;在 Xcode 設備管理器中壓根找不到對應的 Apple Watch 設備。 大家是否已將 Apple Watch 和 Mac 都重啟一萬多遍了&#xff0c;還是束手無策。 Apple Watch not showing in XCodeApple Watch wo…