我正在试图弄清楚实现某个API目标的正确语法是什么,但是我在努力实现可见性。
我希望能够像Messenger
一样访问msgr.Title.ForSuccesses
实例的成员。
但是,我不希望能够从Messenger.Titles
课程外部实例化Messenger
。
我也愿意将Messenger.Titles变成一个结构。
我猜我需要某种工厂模式或某种东西,但我真的不知道我该怎么做。
见下文:
class Program {
static void Main(string[] args) {
var m = new Messenger { Title = { ForErrors = "An unexpected error occurred ..." } }; // this should be allowed
var t = new Messenger.Titles(); // this should NOT be allowed
}
}
public class Messenger {
// I've tried making this private/protected/internal...
public class Titles {
public string ForSuccesses { get; set; }
public string ForNotifications { get; set; }
public string ForWarnings { get; set; }
public string ForErrors { get; set; }
// I've tried making this private/protected/internal as well...
public Titles() {}
}
public Titles Title { get; private set; }
public Messenger() {
Title = new Titles();
}
}
答案 0 :(得分:7)
你只需要将标题设为私有并公开界面而不是它。
class Program {
static void Main(string[] args) {
var m = new Messenger { Title = { ForErrors = "An unexpected error occurred ..." } }; // this is allowed
var t = new Messenger.Titles(); // this is NOT allowed
}
}
public class Messenger {
public interface ITitles {
string ForSuccesses { get; set; }
string ForNotifications { get; set; }
string ForWarnings { get; set; }
string ForErrors { get; set; }
}
private class Titles : ITitles {
public string ForSuccesses { get; set; }
public string ForNotifications { get; set; }
public string ForWarnings { get; set; }
public string ForErrors { get; set; }
}
public ITitles Title { get; private set; }
public Messenger() {
Title = new Titles();
}
}
答案 1 :(得分:0)
如果您创建Titles
构造函数internal
,您将只能在程序集中创建它的实例。如果它是一个API,也许这将受到足够的保护?您可以在BCL中看到此模式(例如只能通过调用HttpWebRequest
创建的WebRequest.Create
)。
答案 2 :(得分:0)
Why Would I Ever Need to Use C# Nested Classes嵌套类型永远不会从外部类型初始化。
答案 3 :(得分:0)
好吧,你可以使标题成为一个结构,并使构造函数公开或内部。这样,每当客户端通过Title属性获取Titles实例的副本时,他们将获得值,而不是引用。他们可以修改该值,但是要将该更改应用于对象的内部状态,他们需要能够通过Title属性再次设置该值。他们不能,因为你将Title setter标记为private。
在内部更改值时,您必须执行相同的操作。例如:
// Your constructor...
public Messenger()
{
Titles t = new Titles();
t.ForSuccesses = "blah";
Title = t;
}
您可以在内部执行此操作,因为您可以访问Title属性的私有设置器。
主要的缺点是它可能会混淆框架的客户端,因为看起来你可以设置Titles实例的值,但是没有真正的方法让他们将更改提交回Messenger类。