試煉14 - 開始練習組合技3 反射 + 泛型

2022 鐵人賽文 搬回點部落

開始試煉

今天的試煉 是組合技3了
反射 (Reflection) 是我在面試工程師時 一定會問到的部分
最常聽到的知道反射 但是沒用過
利用這次試煉來分享一個反射的例子

情境是 需要把一筆資料 修改前修改後的異動記錄下來 若都沒有異動就不需要
比如說修改前的DNS 是Google 8.8.8.8 改成 Hinet 168.95.1.1
就要記錄成
Google => Hinet
8.8.8.8 => 168.95.1.1

範例Code如下

void Main()
{
    var before = new SiteDto() { Name = "Google", Server = "8.8.8.8" };
    var after = new SiteDto() { Name = "Hinet", Server = "168.95.1.1" };
    Console.WriteLine("*****************************************");
    Console.WriteLine(SiteDtoDetailedCompare(before, after));
}
string SiteDtoDetailedCompare(SiteDto before, SiteDto after)
{
    var variances = new List<string>();
    if (before.Name != after.Name)
    {
        variances.Add($"{before.Name} => {after.Name}");
    }
    if (before.Server != after.Server)
    {
        variances.Add($"{before.Server} => {after.Server}");
    }
    return string.Join("\r\n", variances);
}
public class SiteDto
{
    public string Name { get; set; }
    public string Server { get; set; }
}

長官看過後非常喜歡 就其他功能都要加上 然後你看者某一個class有快50個欄…

這時候可以嘗試看看反射吧
用反射+泛型就可以寫出一個通用的方法
範例如下

void Main()
{
    var before = new SiteDto() { Name = "Google", Server = "8.8.8.8" };
    var after = new SiteDto() { Name = "Hinet", Server = "168.95.1.1" };
    Console.WriteLine("*****************************************");
    Console.WriteLine(DetailedCompare(before, after));
}
string DetailedCompare<T>(T before, T after) where T : new()
{
    if (before == null && after == null) return String.Empty;
    if (before == null) before = new T();
    if (after == null) after = new T();

    Type type = typeof(T);
    var variances = new List<string>();
    var properties = type.GetProperties(
        BindingFlags.Public | BindingFlags.Instance);
    foreach (PropertyInfo property in properties)
    {
        var targetProperty = type.GetProperty(property.Name);
        object beforeValue = targetProperty.GetValue(before) ?? string.Empty;
        object afterValue = targetProperty.GetValue(after) ?? string.Empty;
        if (beforeValue.Equals(afterValue)) continue;
        variances.Add($"{beforeValue} => {afterValue}");
    }
    return string.Join("\r\n", variances);
}
public class SiteDto
{
    public string Name { get; set; }
    public string Server { get; set; }
}

反射+泛型 這組合技也是十分強大,下次遇到麻煩的需求就可以想想有沒有更好的解法

結束試煉

反射 是比較困難的 當你還不會反射時你會覺得程式碼就像是2D的
開始運用反射後 程式碼變成有3D的感覺 可以換個面向看待
所以反射是很值得學習的

參考
詳解.NET 反射中的BindingFlags 以及常用的BindingFlags 使用方式

如果內容有誤請多鞭策謝謝