是否有必要将每个 ManagementObject 都处理掉?

2024-04-17

我注意到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(使用前将#替换为@)

是否有必要将每个 ManagementObject 都处理掉? 的相关文章

随机推荐