Lazyがインスタンスプロパティを使用してシングルトンのインスタンスを操作してプロパティを提供する場合はどうでしょうか?これらのフィールドは、私たちがクラス内部から作業しているので(巧妙な)、プライベートにすることもできます。実行中に初めてSingleton.Instanceが参照されるまで、すべてのことが怠惰です。ただし、コードがPersonプロパティを取得しようとする前に、プライベートフィールドに適切な値が設定されていなければなりません。シングルトンがインスタンス化したときに彼らが熱心に読み込まれたら、それは問題ありません。
C# In Depthから借りて、ここにはシングルトンを参照するラムダを使用して初期化された、完全に怠惰な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{}
EDIT:あなたはIoCのを持っている場合は、IoCのを使用しています。現在、パターンを混合しようとしています。ランタイムルールを使用してインスタンスクラスをシングルトンに「昇格」するのにIoCを使用していますが、このフォックスシングルトンのインスタンススコープのデータフィールドに基づいてコンパイラが強制する遅延静的プロパティをインスタンス化しようとしています。これは単に動作しません
IoCになったら、すべての依存関係を登録して注入する必要があります。 PersonManagerをNinjectでIPersonManagerの実装として登録し、次にIPersonManagerを生成するFuncを与えることができるメインシングルトンDataAdapterのコンストラクタを作成します。通常、この目的のためにカスタム関数を定義できます。この場合、IoCを使用して、コンテナに保持されている単一のDataAdapterインスタンスから必要なインスタンスデータを提供します。
注意:これらのデータフィールドは、重大な醜悪な反射を避けるために、公に読めるようになっている必要があります。フィールドを読み取り専用フィールドまたは取得専用プロパティとして定義して、ユーザーがそれらを改ざんするのを防ぐことができますが、消費者はそれらを見ることができます。
EDIT 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);
}
あなたが値を持つ、彼らはオブジェクトのコンストラクタ内の値が割り当てられていないオブジェクトについて間違っています。私はnull参照例外を取得していないよ、私はこれらのフィールドが見つかりませんので、コンパイルエラーが表示されます。 私が始めている私の(作業中の)ダブルチェックロックソリューションよりも、あなたが提案していることがどのように優れているか分かりません。 – Arbiter
@Arbiterあなたがそれらを初期化しているコードからはっきりしていませんでした。 KeithSはあなたのために働くべきです。私はパターンを混ぜないという提案をしています。 – sarvesh