プロパティは、MongoWrapper
の_fileName
が Processor.Process()
方法で初期化することは、利用できません。
あなたはが使用できないと言うとき、私はあなたが文字列_fileName
に値が割り当てられていないことを意味していることを前提としています。他の何かを意味するなら、あなたはこの答えを無視するかもしれません。
割り当てられていない理由は、おそらく2つの異なる参照を注入し、デフォルトのTransientLifetimeManager
を使用しているためです。コンテナは 過渡生涯マネージャを使用するため
あなたは構成のタイプを登録
Understanding Lifetime Managers
、または RegisterTypeメソッドを使用して、デフォルトの動作です。 Resolve またはResolveAllメソッドを呼び出すたびに、または依存関係メカニズムによって インスタンスが他のクラスに挿入されると、 の新しいインスタンスが登録、マップ、または要求された型で作成されます。
これは、あなたがProcessor
を解決するとき、それはMongoWrapper
の1つのインスタンスを取得し、あなたがRepository
を解決するときに別のものを得ることを意味します。毎回の注射で新しくなった。このようなことの
考える:あなたが見たよう
var processor = new Processor(new Repository(new MongoWrapper()), new MongoWrapper());
、それは二つの異なるMongoWrapper
を作成しています。これを解決するにはいくつかの方法があります。
LifetimeManager
をもう1つ使用してください。 PerResolveLifetimeManager
はおそらくあなたが望むものです。
この寿命マネージャの動作はTransientLifetimeManager等 であるが、 デフォルトのビルドプランに信号を提供し、インスタンスはビルドアップオブジェクトグラフを横切っ を再利用するようにタイプをマーキング。再帰の場合、オブジェクトが PerResolveLifetimeManagerで登録されている場合、 シングルトン動作が適用されます。
ので、同じようにそれを登録します。
var mongoWrapper = new MongoWrapper();
var processor = new Processor(new Repository(mongoWrapper), mongoWrapper);
2.使用ContainerControlledLifetimeManager
、あなたのIMongoWrapper
シングルトンを作成し、これを使用します。このようなことの
container.RegisterType<IMongoWrapper, MongoWraper>(new PerResolveLifetimeManager());
考えます常に同じ参照。 IMongoWrapperの使い方によっては、これはあなたが望むものかもしれません。このシナリオでは、具体的に_fileName
をstatic
(上記のとおり)に設定するようになりますが、IMongoWrapper
は全体でstatic
となります。
既存のオブジェクト をシングルトンインスタンスとして登録するContainerControlledLifetimeManager。このライフタイムマネージャのUnityは、 ResolveメソッドまたはResolveAllメソッドを呼び出すたびに、または依存関係メカニズムが インスタンスを他のクラスに挿入すると、登録されたタイプまたはオブジェクトの同じインスタンスを 返します。
container.RegisterType<IMongoWrapper, MongoWraper>(new ContainerControlledLifetimeManager());
割り当てIMongoWrapper
手動。しかし、これはIoCを使用する目的全体を敗北させるでしょう。
public class Processor : IProcessor
{
private IRepository _repository;
private IMongoWrapper _mongoWrapper;
public Processor(IRepository repository, IMongoWrapper mongoWrapper)
{
_repository = repository;
_mongoWrapper = mongoWrapper;
_repository.SetWrapper(mongoWrapper);
}
public void Process()
{
_mongoWrapper.Initialise("path");
_repository.Save();
}
}
そして、あなたのリポジトリ:私は私はあなたのデザインに関するStevenに同意することを言わなければならない、と述べているすべてで
public class Repository : IRepository
{
private IMongoWrapper _mongoWrapper;
public Repository()
{
}
public void SetWrapper(IMongoWrapper wrapper)
{
_mongoWrapper = wrapper;
}
public void Save()
{
_mongoWrapper.Log();
}
}
。あなたは本当に両方のクラスにIMongoWrapper
の同じ参照を注入する必要がありますか?そして、Repository
で使用できるように、Processor
は本当にIMongoWrapper
に値を設定する必要がありますか?それはあなたに後で来るために戻ってくる可能性のある奇妙な依存関係の種類を作り出します。設計を解決する答えが良いかもしれないが、私は実際の仕事に焦点を当てる。
UPDATE:あなたは
最善の解決策だと思いますか?ライフタイムマネージャを シングルトンとして設定するか、リポジトリクラスのファイル名の値を設定するにはどうすればよいですか?
私にとっては、_fileName
は1つのリクエスト/スレッド/サイクルで使用されるコンテキスト変数です。したがって、それに応じてそれを処理することができます。あなたが実際に望むならば、MongoWrapper
をシングルトンとして設定してください。それを維持する責任を負うようにしてください_filePath
。
しかし、_fileName
を特定のスコープ(スレッドやリクエストなど)のコンテキスト変数として保持したい場合は、an answer for a similiar questionというコードを使用できます。 idéaは、IMongoWrapper
の別の参照に依存するのではなく、_fileName
のコンテナを共有できるということです。 IOperationContext
の場合は、を基にしたthe answer I wroteのコードを確認してください。
最初にFilePathを保持するクラス。これは単なる文字列でもあります。
public class ContextInfo : IContextInfo
{
public string FilePath {get; set;}
}
public interface IContextInfo
{
string FilePath {get; set;}
}
次に、IOperationContext<IContextInfo>
を使用するラッパー。
public class RequestContext : IRequestContext
{
private readonly IOperationContext<IContextInfo> _operationContext;
public RequestContext(IOperationContext<IContextInfo> operationContext)
{
_operationContext = operationContext;
}
public IContextInfo ContextInfo
{
get
{
if (_operationContext.Items.ContainsKey("ContextInfoString"))
{
return _operationContext.Items["ContextInfoString"];
}
return null;
}
set
{
_operationContext.Items["ContextInfoString"] = value;
}
}
}
プロセッサにIRequestContext
を注入します。
public class Processor : IProcessor
{
private IRepository _repository;
private IMongoWrapper _mongoWrapper;
private IRequestContext _requestContext
public Processor(IRepository repository, IMongoWrapper mongoWrapper, IRequestContext requestContext)
{
_requestContext = requestContext
_repository = repository;
_mongoWrapper = mongoWrapper;
}
public void Process()
{
// Set the context variable.
_requestContext.ContextInfo = new ContextInfo { FilePath = "path" });
// Now it will be set for a specific lifetime.
_repository.Save();
}
}
今変数が設定されている、とあなたはどこにそれを使用することができます...
public class MongoWrapper : IMongoRWrapper
{
private IRequestContext _requestContext;
public MongoWrapper(IRequestContext requestContext)
{
_requestContext = requestContext;
}
private void IsInitialised()
{
if (string.IsNullOrEmpty(_requestContext.ContextInfo.FilePath))
throw new InvalidOperationException(
Resource.MongoRepositoryHelper_must_be_initialised);
}
}
しかし、再び、それはすべてあなたがfileName
を使用する傾向があるかに依存し、何それは寿命だことでなければなりません。変数の所有権について考えてみましょう。それはIMongoWrapper
によって所有されるべきですか?それとも、アプリケーション全体で使用されているものですか?これらの回答の質問はあなたを正しい方向に導くはずです。
なぜ 'Process'が' MongoWrapper'へのパスを渡す必要がありますか?そのデザインは匂いがする。 – Steven
プロセスメソッドは実際にはWindowsサービスによって呼び出され、パスはサービスがフォルダの場所から取得したファイル名です。常に変化します。 –
これは 'Proces'メソッドが呼び出されるたびに変わるか、またはWindowsサービスの実行中に変更されないこの設定値ですか? – Steven