如何限制对嵌套类成员的访问来封闭类?
是否可以指定一个嵌套类的成员可以被封闭的类访问,而不是其他类?
这里是一个问题的例子(当然我的实际代码有点复杂…):
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); } }
在这种情况下,您可以:
- 使构造函数内部 – 这阻止了这个程序集之外创build新的实例或…
- 重构
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; } } // ... }