那么,如果 Lazy 使用 Instance 属性来处理你的单例实例来为自己提供属性呢?这些字段仍然可以是私有的,因为我们是在类内部使用它们(聪明),并且整个事情仍然是惰性的,直到在执行期间第一次引用 Singleton.Instance。但是,在您的代码尝试获取 Person 属性之前,私有字段必须具有正确的值。如果在 Singleton 实例化自身时它们被急切地加载,那很好。
借用C# In Depth,这是一个准懒惰的 Singleton,它具有使用引用 Singleton 的 lambda 初始化的完全懒惰的 Person 成员。
public sealed class Singleton
{
private static readonly Singleton instance = new Singleton();
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
static Singleton()
{
}
private Singleton()
{
//I HIGHLY recommend you initialize _adusername,
//_adpassword and client here.
}
public static Singleton Instance
{
get
{
return instance;
}
}
private static readonly Lazy<IPersonManager> _person =
new Lazy<IPersonManager>(() => new PersonManager(Instance._adUserName, Instance._adPassword, Instance.client));
public static IPersonManager Person { get { return _person.Value; } }
private object _adUserName;
private object _adPassword;
private object client;
}
public class PersonManager:IPersonManager {}
public interface IPersonManager{}
编辑:如果您有 IoC,请使用 IoC。您目前正在尝试混合模式;您正在使用 IoC 使用运行时规则将实例类“提升”为单例,但随后尝试基于此人造单例的实例范围数据字段实例化编译器强制执行的惰性静态属性。这根本行不通
一旦你使用 IoC,每个依赖项都应该被注册和注入。向 Ninject 注册 PersonManager 作为 IPersonManager 实现,然后为您的主单例 DataAdapter 创建一个构造函数,该构造函数可以被赋予一个生成 IPersonManager 的 Func。您通常可以为此目的定义一个自定义函数,在您的情况下,它将利用 IoC 从容器中保存的单个 DataAdapter 实例中提供所需的实例数据。
警告:这些数据字段现在必须是公开可读的,以避免一些严重丑陋的反射;您可以将字段定义为只读字段或仅获取属性以防止人们篡改它们,但您的消费者将能够看到它们。
编辑2:这是我的想法:
//in your Ninject bindings:
kernel.Bind<DataAdapter>().ToSelf().InSingletonScope();
kernel.Bind<PersonManager>().ToSelf().InSingletonScope();
//to bind the interface
kernel.Bind<IPersonManager>()
.ToMethod(c =>{
var adapter = kernel.Get<DataAdapter>();
//this is why these fields would have to be public
var arg1 = new ConstructorArgument("adUserName", adapter._adUserName)
var arg2 = new ConstructorArgument("adPassword", adapter._adPassword)
var arg3 = new ConstructorArgument("client", adapter.client)
//the names of the arguments must match PersonManager's constructor
c.Kernel.Get<PersonManager>(arg1, arg2, arg3);
});
//now in your DataAdapter, specify a constructor like this, and Ninject will provide:
public DataAdapter(Func<IPersonManager> personFunc)
{
//_person should obviously not be instantiated where it's defined in this case
_person = new Lazy<IPersonManager>(personFunc);
}