[英]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.