阻止访问继承的成员

本文关键字:成员 继承 访问 | 更新日期: 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访问修饰符。如果你的插件管理器需要访问这些值,你必须确保它确实可以访问——例如,你可以让负责处理这些数据的部分成为PluginBasesealed嵌套类。

但最终,问题是——为什么?尝试强制派生类以避免访问这些成员没有什么意义(为什么首先要有这些成员?(。也许在一个明确实现的接口中拥有这些属性就足够了?这样,您仍然可以使用例如((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.在此处输入链接描述