阻止访问继承的成员
本文关键字:成员 继承 访问 | 更新日期: 2023-09-27 18:02:20
这个问题可能有点奇怪。场景如下:
- 有一个名为
IPlugin
的插件接口 - 插件(实现接口(有一个抽象基类
PluginBase
- 这些存储在类库中
现在,每个人都应该能够通过创建一个新的类库和一个从PluginBase
派生的插件类来创建自己的插件。
PluginBase
类将提供许多公共属性,这些属性从基本工具中用于与插件接口通信。这是通过反思来实现的;工具搜索基于接口CCD_ 5的类并创建该类的实例。
现在的问题是,这些公共属性是插件机制所必需的,但不应该从派生的插件类中访问或更改。简而言之:用户定义的插件类不应该能够访问其基类PluginBase
的几个公共成员。
这有可能吗?我知道我通常应该对这些属性使用private
(所以派生类不能访问它们(,但由于基类也充当插件接口,这是不可能的。
解决方案(基于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
接口的。为什么?选择一个,然后使用它。框架中没有规定必须根据某个接口搜索插件。
为了防止派生类访问其父类的成员,可以使用private
访问修饰符。如果你的插件管理器需要访问这些值,你必须确保它确实可以访问——例如,你可以让负责处理这些数据的部分成为PluginBase
的sealed
嵌套类。
但最终,问题是——为什么?尝试强制派生类以避免访问这些成员没有什么意义(为什么首先要有这些成员?(。也许在一个明确实现的接口中拥有这些属性就足够了?这样,您仍然可以使用例如((IPluginBase)plugin).SomeProperty
,但不能使用plugin.SomeProperty
。这并不是说他们无论如何都无法使用反射来获取数据。
现在的问题是,这些公共财产对于插件机制,但不应从派生插件类。
您尝试做的事情实际上是不可能的,因为若类实现了抽象类——它必须知道它的所有成员。你能做的就是这样做:
1( 为您的界面添加内部关键字
internal interface IPlugin
{
int MyProperty1 {get; set;}
int MyProperty2 {get; set;}
int MyProperty3 {get; set;}
void HiddenMethod();
}
2( 实现要显式隐藏的属性/方法:
abstract class PluginBase : IPlugin
{
public int MyProperty1 { get; set; }
public int MyProperty2 { get; set; }
int IPlugin.MyProperty3 { get; set; }
void IPlugin.HiddenMethod() {}
}
现在,您可以通过IPlugin接口在主解决方案中使用所有隐藏的方法和属性,方法是:
IPlugin instance = new MyConcretePlugin();
instance.MyProperty3 = 10;
instance.HiddenMethod();
IPlugin接口现在不能从任何其他解决方案访问(除了持有它的解决方案(,因此所有隐藏成员都可以访问。
您可以在方法和属性上使用内部,这些方法和属性只能在程序集中使用
public class PluginBase : IPlugin
{
// Only accessible within the same assembly
internal static int x = 0;
}
您可以使用InternalsVisibleToAttribute.在此处输入链接描述