我有一个配置类商店应用程序配置。目前我正在使用静态类。一些配置与一个主题相关,所以我想将它们组织成一个嵌套类,所以我可以引用这样的配置:
AppConfig.Url
AppConfig.LogSettings.FileSize
我有两个选项,要么使用静态嵌套类
public static class AppConfig
{
public static class LogSettings
{
public static int FileSize {get; set;}
}
}
或声明一个类,但添加一个静态属性:
public static class AppConfig
{
public class LogSettings
{
public int FileSize {get; set;}
}
public static LogSettings logSettings { get; private set; }
}
但是,它们都不能保护被其他类修改的嵌套类成员FileSize,即使我使用private set
来保护公共静态属性。
也许我不应该使用嵌套类来实现它?有什么建议吗?
答案 0 :(得分:7)
到目前为止给出的其他解决方案基本上要求将属性设置为一次。我非常支持不可变对象,但它们并不总是实用的;是否有可能解决您的问题并使该属性变得可变?
这实际上是您提出的更普遍问题的一个特例:我们如何将内部类的某些成员标记为只能 到外部类,但不< / em>到那个类之外的任何东西?
如何做到这一点并不明显,但这非常容易。解决方案的关键是要记住接口可能是私有实现细节。 C#要求基类至少与从它派生的类一样可访问,但C#不要求实现的接口为作为实现它的类可以访问!
using System;
public static class Outer
{
private interface IPrivates
{
string Name { set; }
}
public readonly static Inner TheInner = new Inner();
private readonly static IPrivates TheInnerPrivates = TheInner;
public class Inner : IPrivates
{
public string Name { get; private set; }
string IPrivates.Name { set { this.Name = value; } }
}
public static void DoIt()
{
TheInnerPrivates.Name = "abc";
}
}
public class Program
{
public static void Main()
{
Outer.DoIt();
Console.WriteLine(Outer.TheInner.Name);
}
}
Outer
内的代码可以通过界面访问Inner
的私有成员。 Outer
之外的代码除了Inner
的公共成员之外无法看到任何其他内容,因为他们查看私有成员所需的界面本身就是私有的。
答案 1 :(得分:2)
我投票支持埃里克的答案,但是想把它作为'需要考虑的事情'。
public class Tester
{
public Tester()
{
AppConfig.LogSettings.FileSize = 5; // compile error
Console.WriteLine(AppConfig.LogSettings.FileSize); // works
}
}
public static class AppConfig
{
// just an example of setting the value in the outer class
private static void SetFileSize(int size)
{
fileSize = size; // internal only setting works
}
private static int fileSize; // a member of AppConfig still
public static class LogSettings
{
public static int FileSize
{
get { return fileSize; } // internal classes can access private members of the outer class
}
}
}
当您从外部访问AppConfig时,您可以获得所需的分组,但是在AppConfig类中,“分组”只是公开公开getter,实际的成员变量仍然属于AppConfig。
这是有效的,因为内部类可以访问外部类的私有成员。
因此,如果您的分组目标主要是关于公共界面 - 您如何获得价值 - 这种方法更简单,但如果您的目标也是内部分组......那么显然它无法实现。
答案 2 :(得分:1)
一种选择是使用嵌套类的构造函数来初始化值。例如:
public static class AppConfig {
static AppConfig() {
Log = new LogSettings(1);
}
public class LogSettings {
public LogSettings(int fileSize) {
FileSize = fileSize;
}
public int FileSize { get; private set; }
}
public static LogSettings Log { get; private set; }
}
然后其他类仍然可以创建LogSettings
的实例,但无法修改您的实例。
答案 3 :(得分:0)
如果这是您想要的方法,我会看到两个选项:
您将配置文件加载和解析的所有逻辑提取到一个单独的项目(库)中,而不是标记您的setter internal
和其他无法访问的库他们了。
您可以实现一个更明确的属性,它不允许设置两次值,如:
private int? _fileSize;
public int FileSize {
get { return _fileSize ?? 0; }
set {
if (_fileSize.HasValue) {
throw new InvalidOperationException("You can only set the value once");
}
_fileSize = value;
}
}
我经常使用的另一个选项是将配置的不同部分的解析封装到子类中。您在构造函数中提供该信息,并且该类初始化自身。 (就像Evk commented in the meanwhile)