这个问题可能有点奇怪。场景如下:
- 有一个名为
IPlugin
的插件接口(interface) - 有一个名为
PluginBase
的插件抽象基类(它实现了接口(interface)) - 这些存储在类库中
现在每个人都应该能够通过创建一个新的类库和一个派生自 PluginBase
的插件类来创建自己的插件。
PluginBase
类将提供许多公共(public)属性,这些属性从基础工具中用于与插件接口(interface)进行通信。这是通过反射完成的;该工具搜索基于接口(interface) IPlugin
的类并创建该类的实例。
现在的问题是,这些公共(public)属性是插件机制所必需的,但不应从派生插件类访问或更改。简而言之:用户定义的插件类不应该能够访问其基类 PluginBase
的多个公共(public)成员。
这有可能吗?我知道我通常应该为这些属性使用 private
(因此派生类无法访问它们)但是由于基类也充当插件接口(interface),所以这是不可能的。
解决方案(基于 Fabjan 和 Luaan 的回答):
// basic plugin interface (IPlugin.dll)
public interface IPlugin
{
// plugin communication interface
string SomeProperty { get; set; }
void SomeMethod();
// public interface
string Name { get; }
void Run();
}
// plugin base class (IPlugin.dll)
public class PluginBase : IPlugin
{
string IPlugin.SomeProperty
{
get { return "Something"; }
set { /* ... */ }
}
void IPlugin.SomeMethod()
{
Console.WriteLine("Something");
}
public string Name
{
get { return "MyName"; }
}
public void Run()
{
// ...
}
}
// user-defined plugin (MyPlugin.dll)
public class MyPlugin : PluginBase
{
public MyPlugin()
{
// will not work
this.SomeProperty ...
}
}
// main assembly
static void Main(string[] args)
{
Assembly asm = Assembly.LoadFrom(@"path\to\assembly");
var type = asm.GetTypes().FirstOrDefault(t => t.GetInterface("NamespaceOfIPlugin.IPlugin", true) != null);
NamespaceOfIPlugin.IPlugin plugin = (NamespaceOfIPlugin.IPlugin)Activator.CreateInstance(type);
// works as expected
plugin.SomeMethod();
}
最佳答案
如果您不想公开这些属性,请不要公开它们。
您的解决方案的架构充其量似乎是不稳定的。您期望(甚至要求)所有插件都实现PluginBase
,但您却根据IPlugin
接口(interface)搜索插件。为什么?选择一个,然后滚动。框架中没有规定必须根据某个接口(interface)来搜索插件。
要防止派生类访问其父类的成员,您可以使用 private
访问修饰符。如果您的插件管理器需要访问这些值,您必须确保它确实如此 - 例如,您可以使负责处理此数据的部分成为 sealed
PluginBase 的嵌套类
。
但最后,问题是 - 为什么?试图强制派生类避免访问这些成员毫无意义(为什么首先要有这些成员?)。也许将这些属性放在一个显式实现的接口(interface)中就足够了?这样你仍然可以使用例如((IPluginBase)plugin).SomeProperty
,但不是 plugin.SomeProperty
。反正他们也不是不能使用反射获取数据。
关于c# - 防止访问继承的成员,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31380841/