我希望有一个Singleton,它将在程序启动时自动实例化.
我所说的"自动实例化"是指Singleton中的代码应该在程序启动时实例化,而不需要其他代码的任何调用或声明.
所以我希望在程序启动时实例化并写出"MySingleton Instantiated"之类的东西(没有主代码做任何事情)...
static class MySingleton { private static MySingleton self = new MySingleton(); protected MySingleton() { System.Console.WriteLine("MySingleton Instantiated"); } }
除了这不起作用,因为C#只会在需要时初始化类的静态成员,即当它们被访问/等时.
那我该怎么办?可以这样做吗?
我没有亲自使用C++(暂时没有使用C++),但我很确定它可以在C++中完成但不确定C#.
任何帮助表示赞赏.谢谢.
我真正想要做的就是......将会有很多这些单例类(随着时间的推移可以添加更多),所有这些类都将继承自一个公共(抽象)父类(也就是说. PClass).
PClass将有一个静态成员,它是PClasses的集合......以及一个将自己添加到集合中的构造函数......
然后理论上所有的单例都会自动添加到集合中(因为当它们被实例化时,调用基类PClass构造函数并将新对象添加到集合中)...然后可以在不知道任何关于什么子项的情况下使用该集合(已经实现了单例类,并且可以随时添加新的子(单例)类,而无需更改任何其他代码.
不幸的是,我无法让孩子们(单身人士)自我实例化......搞砸了我的小计划,导致了这篇文章.
希望我解释得那么好.
PS.是的,我意识到单身人士和他们的使用有不好的感觉......但有时他们很有用,即使撒旦自己做了单身人士,我仍然想知道我的问题是否能在C#中实现.非常感谢大家.
克里斯提到的IoC方法可能是最好的,但是我没能想到的"最佳"解决方案是用反射和属性做一些时髦的事情:
public class InitOnLoad : Attribute { public static void Initialise() { // get a list of types which are marked with the InitOnLoad attribute var types = from t in AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes()) where t.GetCustomAttributes(typeof(InitOnLoad), false).Count() > 0 select t; // process each type to force initialise it foreach (var type in types) { // try to find a static field which is of the same type as the declaring class var field = type.GetFields(System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic).Where(f => f.FieldType == type).FirstOrDefault(); // evaluate the static field if found if (field != null) field.GetValue(null); } } } [InitOnLoad] public class Foo { public static Foo x = new Foo(); private Foo() { Console.WriteLine("Foo is automatically initialised"); } } public class Bar { public static Bar x = new Bar(); private Bar() { Console.WriteLine("Bar is only initialised as required"); } }
通过调用InitOnLoad.Initialise()添加到main方法中.
您可以取消该属性,但这可能会导致不必要的类型被初始化并且不必要地消耗内存(例如上面代码中的Bar).
还值得注意的是,这不会处理动态加载的任何程序集中包含的类型,除非您再次调用Initialise,而是基于您的问题("在程序启动时自动实例化"),这听起来不是问题为了你.
虽然.NET模块理论上可以(IIRC)对模块负载等作出反应,但这不能通过C#获得.在某些框架(如ASP.NET)中,您可以通过配置使用钩子,例如通过处理程序或通过global.asax.cs进行黑客攻击 - 但是,对于常规C#应用程序(控制台,winform等),您必须手动触发它.例如,Main
将调用承载入口点的类上的静态构造函数.
那么:这里的用例是什么?什么时候延迟加载方法不行?