名称仅在Main中获得一个值,而在public plname
中却没有,但是我不希望人们使用Main他们像下面这样使用public plname
的问题,并且覆盖也不起作用,有人可以帮我吗
public class Singleton<T> where T : new()
{
public static readonly T Api = new T();
protected Singleton() { Console.WriteLine("Inited"); }
}
public class SomeSingleton : Singleton<SomeSingleton>
{
public string Name { get; set; }
public SomeSingleton() { }
public virtual string getPluginName() { return Name; }
}
public class plname : SomeSingleton
{
public plname() { // this not works
Name = "test";
}
public static void Main(string[] args)
{
Api.Name = "testing"; // this works
Console.WriteLine(Api.getPluginName());
Console.ReadLine();
}
public override string getPluginName()
{
return "this not works"; // this not works
}
}
编辑:
Singleton
和SomeSingleton
类位于.dll文件中,plname
类不在dll中
我想这样使用
public class plname : SomeSingleton
{
public plname {
Name = "test";
}
}
答案 0 :(得分:1)
在Main
方法中,该方法是(间接)继承自Singleton<SomeSingleton>
的类型内的方法,Api
引用Singleton<SomeSingleton>.Api
。这是Singleton<SomeSingleton>
类型的 static 成员。因此,它明确不是既不是SomeSingleton
也不是plname
的新成员。
由于Api
现在是Singleton<SomeSingleton>
的成员,这意味着它仅被初始化一次。那时,它得到的值是new T()
,其中T
是SomeSingleton
。
这意味着,除非您主动更改Api
上存在的实例,否则它将始终引用相同的SomeSingleton
实例,该实例将在没有任何数据(也没有名称)的情况下实例化。
这就是为什么您只做null
时就得到Api.getPluginName()
的原因:因为SomeSingleton
的静态实例从未初始化过名称。而且由于该实例明确地不是plname
的实例,所以plname
的重写方法也将不适用。
因此,您将不得不忍受这样一个事实,即继承单例通常不会真正起作用,因为对原始类型的单例引用不会被神奇地更新。
假设您要编写某种插件系统,那么最好完全不必依靠单例来做到这一点。或者,也可以只用一个单例,即可在某个注册表中注册您的插件。
例如:
public interface IPlugin
{
string Name { get; }
void DoStuff();
}
public static class PluginRegistry
{
private static readonly List<IPlugin> plugins = new List<IPlugin>();
public static IEnumerable<IPlugin> GetPlugins() => plugins;
public static void Register(IPlugin plugin) => plugins.Add(plugin);
}
// And then an example plugin implementation
public class MyPlugin : IPlugin
{
public string Name => "My fancy plugin";
public void DoStuff() => Console.WriteLine("My fancy plugin was called!");
}
在以下时间注册您的插件
PluginRegistry.Register(new MyPlugin());
然后您可以使用PluginRegistry
访问您的插件:
foreach (var plugin in PluginRegistry.GetPlugins())
plugin.DoStuff();
// Output:
// My fancy plugin was called!