如何限制对嵌套类成员的访问来封闭类?

是否可以指定一个嵌套类的成员可以被封闭的类访问,而不是其他类?

这里是一个问题的例子(当然我的实际代码有点复杂…):

public class Journal { public class JournalEntry { public JournalEntry(object value) { this.Timestamp = DateTime.Now; this.Value = value; } public DateTime Timestamp { get; private set; } public object Value { get; private set; } } // ... } 

我想阻止客户端代码创buildJournalEntry实例,但是Journal必须能够创build它们。 如果我公开构造函数,任何人都可以创build实例…但是如果我把它变成私有的, Journal将无法!

请注意, JournalEntry类必须是公共的,因为我希望能够将现有条目公开到客户端代码。

任何build议,将不胜感激!


更新:谢谢大家的input,我最终去公众IJournalEntry接口,由一个私人JournalEntry类实现(尽pipe在我的问题的最后一个要求…)

如果你的类不是太复杂,你可以使用一个公共可见的接口,并将实际的类实现为私有的,或者你可以为JornalEntry类创build一个受保护的构造函数,并从JornalEntry派生一个私有类JornalEntryInstance ,实际上由您的Journal实例化。

 public class Journal { public class JournalEntry { protected JournalEntry(object value) { this.Timestamp = DateTime.Now; this.Value = value; } public DateTime Timestamp { get; private set; } public object Value { get; private set; } } private class JournalEntryInstance: JournalEntry { public JournalEntryInstance(object value): base(value) { } } JournalEntry CreateEntry(object value) { return new JournalEntryInstance(value); } } 

如果你的实际类太复杂了,那么你就可以使构造函数不能完全看不见,你可以使构造函数在内部,所以它只能在程序集中看到。

如果这也是不可行的,你总是可以使构造函数是私有的,并使用reflection来从你的日记类中调用它:

 typeof(object).GetConstructor(new Type[] { }).Invoke(new Object[] { value }); 

现在我想到了,另一种可能性是在内部类中设置的包含类中使用私有委托

 public class Journal { private static Func<object, JournalEntry> EntryFactory; public class JournalEntry { internal static void Initialize() { Journal.EntryFactory = CreateEntry; } private static JournalEntry CreateEntry(object value) { return new JournalEntry(value); } private JournalEntry(object value) { this.Timestamp = DateTime.Now; this.Value = value; } public DateTime Timestamp { get; private set; } public object Value { get; private set; } } static Journal() { JournalEntry.Initialize(); } static JournalEntry CreateEntry(object value) { return EntryFactory(value); } } 

这应该给你你想要的可见性水平,而不需要缓慢反思或引入额外的类/接口

实际上,这个问题有一个完整和简单的解决scheme,不涉及修改客户端代码或创build一个接口。

在大多数情况下,这个解决scheme实际上比基于接口的解决scheme更快,而且更容易编码。

 public class Journal { private static Func<object, JournalEntry> _newJournalEntry; public class JournalEntry { static JournalEntry() { _newJournalEntry = value => new JournalEntry(value); } private JournalEntry(object value) { ... 

使JournalEntry成为一个私有的嵌套types 。 任何公共成员只能在封闭types中看到。

 public class Journal { private class JournalEntry { } } 

如果您需要使JournalEntry对象可用于其他类,请通过公共接口公开它们:

 public interface IJournalEntry { } public class Journal { public IEnumerable<IJournalEntry> Entries { get { ... } } private class JournalEntry : IJournalEntry { } } 

一个简单的方法是使用一个internal构造函数,但通过提供一个只有合法的调用者可以知道的参考来使得调用者certificate他们是谁(我们不需要担心非公开的reflection,因为如果调用者具有访问非公众反思,那么我们已经失去了斗争 – 他们可以直接访问private构造函数); 例如:

 class Outer { // don't pass this reference outside of Outer private static readonly object token = new object(); public sealed class Inner { // .ctor demands proof of who the caller is internal Inner(object token) { if (token != Outer.token) { throw new InvalidOperationException( "Seriously, don't do that! Or I'll tell!"); } // ... } } // the outer-class is allowed to create instances... private static Inner Create() { return new Inner(token); } } 

在这种情况下,您可以:

  1. 使构造函数内部 – 这阻止了这个程序集之外创build新的实例或…
  2. 重构JournalEntry类以使用公共接口,并使实际的JournalEntry类为private或internal。 然后可以将该接口暴露给集合,而隐藏实际的实现。

我提到内部是一个有效的修饰符,然而取决于您的要求,私人可能是更合适的select。

编辑:对不起,我提到了私人构造函数,但你已经在你的问题处理了这一点。 我很抱歉没有正确阅读!

我会使JournalEntry构造函数内部:

 public class Journal { public class JournalEntry { internal JournalEntry(object value) { this.Timestamp = DateTime.Now; this.Value = value; } public DateTime Timestamp { get; private set; } public object Value { get; private set; } } // ... } 
Interesting Posts