![](/img/trans.png)
[英]Can I get PropertyInfo for a field or property in a class without using reflection?
[英]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.