.NET - 如何创建一个类,使得只有一个其他特定类可以实例化它?
我想要进行以下设置:
class Descriptor
{
public string Name { get; private set; }
public IList<Parameter> Parameters { get; private set; } // Set to ReadOnlyCollection
private Descrtiptor() { }
public Descriptor GetByName(string Name) { // Magic here, caching, loading, parsing, etc. }
}
class Parameter
{
public string Name { get; private set; }
public string Valuie { get; private set; }
}
从 XML 文件加载后,整个结构将是只读的。我想让它只有描述符类才能实例化参数。
一种方法是创建一个 IParameter 接口,然后在 Descriptor 类中将 Parameter 类设为私有,但在实际使用中,参数将具有多个属性,我想避免重新定义它们两次。
这有可能吗?
I'd like to have the following setup:
class Descriptor
{
public string Name { get; private set; }
public IList<Parameter> Parameters { get; private set; } // Set to ReadOnlyCollection
private Descrtiptor() { }
public Descriptor GetByName(string Name) { // Magic here, caching, loading, parsing, etc. }
}
class Parameter
{
public string Name { get; private set; }
public string Valuie { get; private set; }
}
The whole structure will be read-only once loaded from an XML file. I'd like to make it so, that only the Descriptor class can instantiate a Parameter.
One way to do this would be to make an IParameter
interface and then make Parameter
class private in the Descriptor class, but in real-world usage the Parameter will have several properties, and I'd like to avoid redefining them twice.
Is this somehow possible?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
使其成为实现特定接口的私有嵌套类。然后,只有外部类可以实例化它,但任何人都可以使用它(通过接口)。示例:
如果您确实必须避免使用接口,则可以创建一个具有所有属性但声明受保护的构造函数的公共抽象类。然后,您可以创建一个私有嵌套类,该嵌套类继承只能由外部类创建的公共抽象,并返回其实例作为基类型。例子:
Make it a private nested class that implements a particular interface. Then, only the outer class can instantiate it, but anyone can consume it (through the interface). Example:
If you really must avoid the interface, you can create a public abstract class that has all of the properties but declares a protected constructor. You can then create a private nested class that inherits from the public abstract that can only be created by the outer class and return instances of it as the base type. Example:
LBushkin 的想法是正确的。如果您想避免重新输入所有属性,只需右键单击类的名称并选择“重构”> “提取接口”,应该为您提供一个包含所有这些属性的接口。 (这在 VS 2008 中有效,我不知道早期版本是否有效。)
C# 通常采用的方法不是避免冗余代码,而是帮助您更快地编写代码。
LBushkin has the right idea. If you want to avoid having to retype all the properties just right-click the name of the class and choose "Refactor" > "Extract Interface", that should give you an interface that contains all those properties. (This works in VS 2008, I don't know about earlier versions.)
C# generally takes the approach that instead of avoiding redundant code, VS will just help you write it faster.
您可以使用标记为“内部”的构造函数。
这样,它对于程序集中的类是公共的,而对于程序集外部的类是私有的。
You could use a constructor marked Internal.
That way it's public to classes in the assembly, and private to classes outside of it.
使用
StrongNameIdentityPermission
属性 和SecurityAction.LinkDemand
选项:您需要提供适当的公钥。因为您要求对
Parameter
类进行链接时(实际上是 JIT 时)检查,这意味着它只能从使用强名称签名的程序集中使用,该强名称使用私钥与您在上面的属性构造函数中提供的公钥相匹配。当然,您需要将Descriptor
类放在单独的程序集中,并相应地为其指定一个强名称。我已经在几个应用程序中使用了这种技术,并且效果非常好。
希望这有帮助。
Mark the class to be "protected" from instantiation (Parameter) with the
StrongNameIdentityPermission
attribute and theSecurityAction.LinkDemand
option:You will need to provide the appropriate public key. Because you are demanding a link-time (JIT-time, in fact) check on the
Parameter
class, this means that it can only be used from an assembly that is signed with a strong name that uses the private key matching the public key that you supply in the attribute constructor above. Of course, you will need to put theDescriptor
class in a separate assembly and give it a strong name accordingly.I have used this technique in a couple of applications and it worked very well.
Hope this helps.
如果您只想使用 Descriptor 类来实例化 Parameter,则可以将 Descriptor 类设置为 Parameter 的嵌套类。 (不是相反)这是违反直觉的,因为容器或父类是嵌套类。
If you want only the Descriptor class to instantiate a Parameter, then you can make the Descriptor class a nested class of Parameter. (NOT the other way around) This is counterintuitive as the container or parent class is the nested class.
还有另一种方法:检查调用堆栈中的调用类型。
There is another way: check the call stack for the calling type.