这个问题可能有点奇怪。方案如下:
IPlugin
PluginBase
现在每个人都应该能够通过创建一个新的类库和一个源自PluginBase
的插件类来创建自己的插件。
PluginBase
类将提供许多公共属性,这些属性从基本工具用于与插件接口通信。这是通过反思完成的;该工具搜索基于接口IPlugin
的类,并创建该类的实例。
现在问题是这些公共属性对于插件机制是必需的,但不应该从派生的插件类访问或更改。简而言之:用户定义的插件类不应该能够访问其基类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();
}
答案 0 :(得分:3)
如果您不希望公开财产,请不要公开。
您的解决方案的体系结构似乎充其量也是不可靠的。您期望(要求偶数)所有插件实现PluginBase
,但您会根据IPlugin
接口搜索插件。为什么?选一个,然后滚动它。框架中没有规则必须根据某个界面搜索插件。
要防止派生类访问其父项的成员,请使用private
访问修饰符。如果您的插件管理器需要访问这些值,您必须确保它确实存在 - 例如,您可以使负责处理此数据的部件成为sealed
嵌套类PluginBase
。< / p>
但最后,问题是 - 为什么?尝试强制派生类以避免访问这些成员(为什么首先有这些成员?),这一点没什么意义。也许将这些属性放在一个可以显式实现的接口中就足够了?这样你仍然可以使用例如((IPluginBase)plugin).SomeProperty
,但不是plugin.SomeProperty
。不管怎样他们都无法使用反射来获取数据。
答案 1 :(得分:2)
现在问题是这些公共财产是必要的 插件机制但不应该从中访问或更改 派生插件类。
你尝试做的事情是不可能的,因为如果类实现抽象类 - 它必须知道它的所有成员。你可以做的是你可以做这样的事情:
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界面现在无法从任何其他解决方案访问(除了持有它的人),因此所有隐藏成员也是如此。
答案 2 :(得分:1)
您可以对仅应在程序集中提供的方法和属性使用internal
public class PluginBase : IPlugin
{
// Only accessible within the same assembly
internal static int x = 0;
}
答案 3 :(得分:0)
您可以使用InternalsVisibleToAttribute。enter link description here