Ну, а что, если Lazy использует свойство Instance для работы с экземпляром вашего синглтона, чтобы обеспечить себя свойствами?Эти поля все еще могут быть закрытыми, так как мы работаем с ними внутри класса (умные), и все это будет оставаться ленивым, пока на Singleton.Instance не будет ссылка впервые во время выполнения.Однако частные поля ДОЛЖНЫ иметь правильные значения, прежде чем ваш код попытается получить свойство Person.Если они активно загружаются при создании экземпляра Singleton, это нормально.
Заимствование из C # In Depth , вот квази-ленивый Singleton с полностью ленивым членом Person, инициализированным с помощью лямбды, котораяссылается на Singleton.
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, КАЖДУЮ зависимость нужно зарегистрировать и ввести.Зарегистрируйте PersonManager в Ninject в качестве реализации IPersonManager, а затем создайте конструктор для основного одноэлементного адаптера данных, которому может быть предоставлен Func, который создает IPersonManager.Обычно для этой цели можно определить пользовательскую функцию, которая в вашем случае будет использовать 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);
}