2017-03-02 10 views
2

私はレジストリ内のキーを検索し、その値を返すために次の方法を使用しています。私はルートキーを使って検索し、ターゲットの相対パスを文字列として渡します。パスを解析する際には、前のキーをベースとして使用して次のレベルを開きます。私は厳密には読み取り専用なので、ベースキーを終了した後でベースキーを閉じる必要がありますか?もしそうなら、それはこれを行う方法ですか?レジストリキーを連鎖させてキーを検索するとき、RegistryKeyを正しく閉じるにはどうすればいいですか?

public static string QueryRegistry (RegistryKey root, string path) 
{ 
    return path.Split(Path.DirectorySeparatorChar) 
    .Aggregate(root, (r, k) => 
    { 
     var key = r?.OpenSubKey(k); 
     r?.Close(); 
     return key; 
    }).GetValue(null).ToString(); 
} 
+0

「RegistryKey」は「IDisposable」です:http://stackoverflow.com/a/9905046/1132334 [this](https://msdn.microsoft.com/en-us/library/microsoft.win32.registrykey(v = versus90).aspx)は、「使用中」の最上部のキーをラップするのに十分であることを示しています。 – dlatikay

+0

@dlatikayそれは、それがルートキーを処分するだけで十分であることを示唆していますか? – Evk

+0

わかりました。はい、私はそれが 'IDisposable'であることを知っていましたが、関数呼び出しでusingステートメントを適用する方法がわかりませんでした。なぜ最上位の鍵だけ?彼らの例では –

答えて

1

だからここにあなたの基本的な問題は、あなたがIDisposableオブジェクトの不確定な数を作成している、とあなたはあなたがそれらを閉じて準備ができているよ時にわからないということです。このような状況で私がしているのは、それらを追跡するためのコレクションを作成し、それが済んだらコレクション内のすべてを破棄することです。ここにあなたのオブジェクトを適切に処分しないというリスクがあります。

public static string QueryRegistry (RegistryKey root, string path) 
{ 
    List<IDisposable> resourceTracker = new List<IDisposable>() { root }; 
    string ret = null; 
    try 
    { 
     ret = path.Split(Path.DirectorySeparatorChar) 
     .Aggregate(root, (r, k) => 
     { 
      var key = r?.OpenSubKey(k); 
      if (key != null) 
      { 
       resourceTracker.Add(key); 
      } 
      return key; 
     }).GetValue(null).ToString(); 
    } 
    finally 
    { 
     foreach (var res in resourceTracker) 
     { 
      res.Dispose(); 
     } 
    } 
    return ret; 
} 

あなたはCERでこれを行うために試みることができるが、私は新しい鍵を開けるかなり確信しては、CLRがとにかくCERとして扱いません意味の割り当てとしてカウントされます。しかし、これはおそらく十分安全であるはずです。クラスはビットを拡張することができることを

public static string QueryRegistry (RegistryKey root, string path) 
{ 
    string ret = null; 
    using (var resourceTracker = new DisposableCollection() { root }) 
    { 
     ret = path.Split(Path.DirectorySeparatorChar) 
     .Aggregate(root, (r, k) => 
     { 
      var key = r?.OpenSubKey(k); 
      if (key != null) 
      { 
       resourceTracker.Add(key); 
      } 
      return key; 
     }).GetValue(null).ToString(); 
    } 
    return ret; 
} 

:その後のように使用することができ

public class DisposableCollection : IList<IDisposable>, IDisposable 
{ 
    private List<IDisposable> disposables = new List<IDisposable>(); 

    #region IList<IDisposable> support 

    public int Count 
    { 
     get 
     { 
      return ((IList<IDisposable>)disposables).Count; 
     } 
    } 

    public bool IsReadOnly 
    { 
     get 
     { 
      return ((IList<IDisposable>)disposables).IsReadOnly; 
     } 
    } 

    public int IndexOf(IDisposable item) 
    { 
     return ((IList<IDisposable>)disposables).IndexOf(item); 
    } 

    public void Insert(int index, IDisposable item) 
    { 
     ((IList<IDisposable>)disposables).Insert(index, item); 
    } 

    public void RemoveAt(int index) 
    { 
     ((IList<IDisposable>)disposables).RemoveAt(index); 
    } 

    public void Add(IDisposable item) 
    { 
     ((IList<IDisposable>)disposables).Add(item); 
    } 

    public void Clear() 
    { 
     ((IList<IDisposable>)disposables).Clear(); 
    } 

    public bool Contains(IDisposable item) 
    { 
     return ((IList<IDisposable>)disposables).Contains(item); 
    } 

    public void CopyTo(IDisposable[] array, int arrayIndex) 
    { 
     ((IList<IDisposable>)disposables).CopyTo(array, arrayIndex); 
    } 

    public bool Remove(IDisposable item) 
    { 
     return ((IList<IDisposable>)disposables).Remove(item); 
    } 

    public IEnumerator<IDisposable> GetEnumerator() 
    { 
     return ((IList<IDisposable>)disposables).GetEnumerator(); 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return ((IList<IDisposable>)disposables).GetEnumerator(); 
    } 

    public void AddRange(IEnumerable<IDisposable> range) 
    { 
     disposables.AddRange(range); 
    } 

    public IDisposable this[int index] 
    { 
     get 
     { 
      return ((IList<IDisposable>)disposables)[index]; 
     } 

     set 
     { 
      ((IList<IDisposable>)disposables)[index] = value; 
     } 
    } 
    #endregion 

    #region IDisposable Support 
    private bool disposedValue = false; // To detect redundant calls 


    protected virtual void Dispose(bool disposing) 
    { 
     if (!disposedValue) 
     { 
      if (disposing) 
      { 
       foreach(var disposable in disposables) 
       { 
        disposable.Dispose(); 
       } 
      } 

      // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below. 
      // TODO: set large fields to null. 

      disposedValue = true; 
     } 
    } 

    // TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources. 
    // ~DisposableCollection() { 
    // // Do not change this code. Put cleanup code in Dispose(bool disposing) above. 
    // Dispose(false); 
    // } 

    // This code added to correctly implement the disposable pattern. 
    public void Dispose() 
    { 
     // Do not change this code. Put cleanup code in Dispose(bool disposing) above. 
     Dispose(true); 
     // TODO: uncomment the following line if the finalizer is overridden above. 
     // GC.SuppressFinalize(this); 
    } 


    #endregion 
} 

:(rory.apが提案多少のような)

これはそうのようなコレクションに抽象化することができ(ConcurrentBagまたはConcurrentQueueなどを使用して)、より具体的なニーズ(例えば、RegistryKeyのコレクション)に拡張することができ、複数の場所でこのロジックが必要な場合に便利です。

+1

また、使い捨てのキーのコレクションを作成し、コレクション上で 'using'ブロックを使用することもできます。コレクションの 'Dispose'メソッドは、それぞれをループして破棄します。より堅牢になるかもしれませんが、もう少しうまくいくでしょう。しかし、その再利用可能なパターンので、それは価値があるかもしれません。 –

+0

良いアイデア - コレクションをより一般的に抽象化した例を示すために編集しました。コレクションは実際には 'Dispose()'だけを気にするので、 'IDisposable'ではなく' RegistryKey'のためにこれを特に行うことでどのくらいの価値が追加されるのか分かりませんが、これはこれが持つ可能性のある他のユースケースに依存します私が推測するアプリ。 –

+0

こんにちは@DanField、これは不確定なライフサイクルの場合の素晴らしい解決策です。私の場合、私はそれを使用した後、鍵がもはや必要ではないことを知っています。OpenSubKeyメソッドを使用して次のレベルを取得します。それは私がそれらをいつ閉じるかを知っていることを意味します。それで、私の方法に問題はありますか?個々の処分と比較して、「使用」ステートメント、またはバルク処分でラッピングすることに利点はありますか? –

関連する問題