簡體   English   中英

如何在不使用反射的情況下獲取傳遞給構造函數的字段或屬性的當前值

[英]How to get the current value of a field or property passed to constructor, without using reflection

我有一類可以在其他地方管理的設置,還有許多需要了解與自己相關的設置的當前值的輔助類的實例。 設置可能隨時更改。

在C ++中,我可以簡單地將對相關設置的引用傳遞給worker類構造函數。 我應該如何在C#中完成此操作? 反射是唯一可靠且簡潔的解決方案嗎?

下面的代碼說明了我要完成的工作,但是當然會失敗,因為在實例化worker時會復制設置的值。 在需要這些值時,我有什么選擇?

我如何才能修改此代碼以實現所需的行為而不會一團糟?

using System;
namespace TestSettings
{
    public static class Settings
    {
        public static bool setting1 { get; set; } = true;
        public static bool setting2 { get; set; } = false;
    }
    public class mWorker
    {
        private string wName;
        private bool wSetting;
        public mWorker(string _name, bool _setting)
        {
            wName = _name;
            wSetting = _setting;
        }
        public void doWork()
        {
            var onOff = (wSetting) ? "ON" : "OFF";
            Console.WriteLine($"Worker {wName} is turned {onOff}");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            // Settings are passed by value when each worker is 
            // instantiated. I want to pass the constructor   
            // something that allows each setting to be read 
            // dynamically whenever it is used. 
            mWorker worker1 = new mWorker("W1", Settings.setting1);
            mWorker worker2 = new mWorker("W2", Settings.setting2);

            Console.WriteLine("\n=====================");
            worker1.doWork();   // Result: "Worker W1 is turned ON"
            worker2.doWork();   // Result: "Worker W2 is turned OFF"

            Settings.setting1 = false;
            Settings.setting2 = true;

            Console.WriteLine("\n=====================");
            worker1.doWork();   // Desired result: "Worker W1 is turned OFF"
            worker2.doWork();   // Desired result: "Worker W2 is turned ON"
            Console.ReadLine();
        }
    }
}

我已經閱讀了許多關於變通辦法的問答,因為無法通過引用傳遞屬性,並且有很多提示和建議,但是沒有一個以任何方式回答我的問題,我可以將其轉化為決定和建議。一個可行的解決方案。 我回到約翰·斯基特(John Skeet)的C#書並重新閱讀,我確定答案就在那兒-但我仍然看不到它。

我知道我可以傳遞屬性名稱並使用反射來獲取值。 魔術弦使我不舒服,但也許NameOf()可以使我滿意。 我知道我可以創建一個名為設置的類,並編寫一個函數來返回給定設置名稱的值。 我了解委托可以提供幫助,但是我看到的示例似乎要求每個設置都委托一個人,我希望有一個簡潔的解決方案。

我以為我可以放棄財產並使用公共領域,傳遞對該領域的引用,但是SO上的一些聰明人建議在與我的問題類似(但不相同)的問題上反對這種方法。

我忍不住覺得這一定是功能上必不可少的一點,並希望有一種普遍接受的方法在C#中進行處理。

您需要將引用類型傳遞給構造函數。 您可以為您的設置創建一個類,並使用要更新的實例。

 public class Setting { public bool isActive { get; set; } } public static class Settings { public static Setting setting1 { get; set; } = new Setting { isActive = true }; public static Setting setting2 { get; set; } = new Setting { isActive = false }; } public class mWorker { private string wName; private Setting wSetting; public mWorker(string _name, Setting _setting) { wName = _name; wSetting = _setting; } public void doWork() { var onOff = wSetting.isActive ? "ON" : "OFF"; Console.WriteLine($"Worker {wName} is turned {onOff}"); } } 

如果您需要保持Settings類不變,則可以執行以下操作:

public static class Settings
{
    public static bool setting1 { get; set; } = true;
    public static bool setting2 { get; set; } = false;
}

public class mWorker
{
    private string wName;
    private Func<bool> wSetting;

    public mWorker(string _name, Func<bool> _setting)
    {
        wName = _name;
        wSetting = _setting;
    }
    public void doWork()
    {
        var onOff = wSetting() ? "ON" : "OFF";
        Console.WriteLine($"Worker {wName} is turned {onOff}");
    }
}

class Program
{
    void Main()
    {
        // Settings are passed by value when each worker is 
        // instantiated. I want to pass the constructor   
        // something that allows each setting to be read 
        // dynamically whenever it is used. 
        mWorker worker1 = new mWorker("W1", () => Settings.setting1);
        mWorker worker2 = new mWorker("W2", () => Settings.setting2);

        Console.WriteLine("\n=====================");
        worker1.doWork();   // Result: "Worker W1 is turned ON"
        worker2.doWork();   // Result: "Worker W2 is turned OFF"

        Settings.setting1 = false;
        Settings.setting2 = true;

        Console.WriteLine("\n=====================");
        worker1.doWork();   // Result: "Worker W1 is turned OFF"
        worker2.doWork();   // Result: "Worker W2 is turned ON"

    }
}

我為您編寫了一個更加C#友好的示例。

我沒有使用setting1和setting2,而是使用了Settings類的兩個不同實例。

    public class Settings: ISettings
    {
        public bool MySetting { get; set; }
    }

在設計中添加worker3 ,需要添加setting3 使用此處顯示的設計,您無需修改Settings類。

這是代碼(接口部分不是必需的,但是允許以后輕松進行模擬,這是一個好習慣)

運行此代碼的結果是

在此處輸入圖片說明

    public interface ISettings
    {
        bool MySetting { get; set; }
    }

    public class Settings: ISettings
    {
        public bool MySetting { get; set; } = true;
    }
    public class mWorker
    {
        private string wName;
        private ISettings settings;
        public mWorker(string _name, ISettings settings)
        {
            wName = _name;
            this.settings = settings;
        }
        public void doWork()
        {
            var onOff = (settings.MySetting) ? "ON" : "OFF";
            Console.WriteLine($"Worker {wName} is turned {onOff}");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var settingsForWorker1 = new Settings() { MySetting = true };
            mWorker worker1 = new mWorker("W1", settingsForWorker1);
            var settingsForWorker2 = new Settings() { MySetting = false };
            mWorker worker2 = new mWorker("W2", settingsForWorker2);

            Console.WriteLine("\n=====================");
            worker1.doWork();   // Result: "Worker W1 is turned ON"
            worker2.doWork();   // Result: "Worker W2 is turned OFF"

            settingsForWorker1.MySetting = false;
            settingsForWorker2.MySetting = true;

            Console.WriteLine("\n=====================");
            worker1.doWork();   // Desired result: "Worker W1 is turned OFF"
            worker2.doWork();   // Desired result: "Worker W2 is turned ON"
            Console.ReadLine();
        }
    }

如果將設置存儲在集合中,則可以輕松地為任意數量的工作人員管理設置:

var settings = new Dictionary<string, Settings>()
{
    { "W1", new Settings() { MySetting = true } },
    { "W2", new Settings() { MySetting = false } },
    { "W3", new Settings() { MySetting = false } },
};

mWorker worker1 = new mWorker("W1", settings["W1"]);
mWorker worker2 = new mWorker("W2", settings["W2"]);

(...)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM