我注意到ManagementObject
is IDisposable
,但它也是从ManagementClass.GetInstances()
and ManagementObjectSearcher.Get()
,这是否意味着我需要处理遇到的每个对象?
Like so:
ManagementObject ret;
foreach(ManagementObject mo in searcher.Get()) {
if( IsWhatIWant(mo) ) ret = mo;
else mo.Dispose();
}
更令人困惑的是:有一个错误ManagementBaseObject
没有正确实施的地方IDisposable
(See using 子句无法调用 Dispose? https://stackoverflow.com/questions/11896282/using-clause-fails-to-call-dispose)所以你需要自己调用它,或者使用一个能够正确调用它的包装器。
这很烦人,因为我有很多ManagementObjectCollections
around.
我创建了一个辅助对象来处理所有创建的管理对象:
public class ManagementObjectDisposer : IDisposable
{
private List<IDisposable> disposables = new List<IDisposable>();
/// <summary>
/// Workaround to dispose ManagementBaseObject properly.
/// See http://stackoverflow.com/questions/11896282
/// </summary>
/// <param name="disposable"></param>
public static void DisposeOne(IDisposable disposable)
{
ManagementBaseObject mbo = disposable as ManagementBaseObject;
if (mbo != null)
mbo.Dispose();
else
disposable.Dispose();
}
public void Dispose()
{
Exception firstException = null;
foreach (IDisposable d in Enumerable.Reverse(disposables))
{
try
{
DisposeOne(d);
}
catch (Exception ex)
{
if (firstException == null)
firstException = ex;
else
cvtLogger.GetLogger(this).Error($"Swallowing exception when disposing: {d.GetType()}", ex);
}
}
disposables.Clear();
if (firstException != null)
throw firstException;
}
public T Add<T>(T disposable) where T : IDisposable
{
disposables.Add(disposable);
return disposable;
}
/// <summary>
/// Helper for ManagementObjectSearcher with adding all objects to the disposables.
/// </summary>
/// <param name="query">The query string.</param>
public IEnumerable<ManagementBaseObject> Search(string query)
{
ManagementObjectSearcher searcher = this.Add(new ManagementObjectSearcher(query));
return EnumerateCollection(searcher.Get());
}
/// <summary>
/// Helper for adding ManagementObjectCollection and enumerating it.
/// </summary>
public IEnumerable<ManagementBaseObject> EnumerateCollection(ManagementObjectCollection collection)
{
this.Add(collection);
ManagementObjectCollection.ManagementObjectEnumerator enumerator = this.Add(collection.GetEnumerator());
while (enumerator.MoveNext())
yield return this.Add(enumerator.Current);
}
}
只需像这样使用它:
using (var moDisposer = new ManagementObjectDisposer())
{
foreach (var mobj = moDisposer.Search("SELECT * FROM Win32_Processor")
Console.WriteLine(mobj["DeviceID"]);
}
注:ManagementClass.GetInstances()
很容易添加到ManagementObjectDisposer
, too.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)