Vanara/Management/DynamicMgmtObject.cs

135 lines
4.1 KiB
C#

using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Dynamic;
using System.Linq;
using System.Management;
namespace Vanara.Management;
/// <summary>A dynamic object to handle WMI <see cref="ManagementBaseObject"/> references.</summary>
/// <seealso cref="System.Dynamic.DynamicObject"/>
/// <seealso cref="System.IDisposable"/>
public class DynamicMgmtObject : DynamicObject, IDisposable
{
private readonly ManagementObject obj;
/// <summary>Initializes a new instance of the <see cref="DynamicMgmtObject"/> class.</summary>
/// <param name="obj">The object.</param>
public DynamicMgmtObject(ManagementObject obj) => this.obj = obj ?? throw new ArgumentNullException(nameof(obj));
/// <summary>Initializes a new instance of the <see cref="DynamicMgmtObject"/> class.</summary>
/// <param name="scope">The scope.</param>
/// <param name="service">The service name.</param>
public DynamicMgmtObject(ManagementScope scope, string service)
{
if (!scope.IsConnected)
scope.Connect();
obj = scope.GetWMIService(service) ?? throw new ArgumentException("Unable to get WMI service", nameof(service));
}
/// <summary>Initializes a new instance of the <see cref="DynamicMgmtObject"/> class.</summary>
/// <param name="wmiclass">The class.</param>
public DynamicMgmtObject(ManagementClass wmiclass) => obj = wmiclass.CreateInstance();
/// <summary>Performs an implicit conversion from <see cref="ManagementObject"/> to <see cref="DynamicMgmtObject"/>.</summary>
/// <param name="mbo">The <see cref="ManagementObject"/>.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator DynamicMgmtObject(ManagementObject mbo) => new(mbo);
/// <inheritdoc/>
public void Dispose() => ((IDisposable)obj).Dispose();
/// <inheritdoc/>
public override IEnumerable<string> GetDynamicMemberNames() => obj.Properties.Cast<PropertyData>().Select(d => d.Name);
/// <inheritdoc/>
public override bool TryConvert(ConvertBinder binder, [NotNullWhen(true)] out object? result)
{
if (binder.Type == typeof(ManagementObject))
{
result = obj;
return true;
}
return base.TryConvert(binder, out result);
}
/// <inheritdoc/>
public override bool TryGetMember(GetMemberBinder binder, [NotNullWhen(true)] out object? result)
{
try { result = obj.GetPropertyValue(binder.Name); return true; }
catch (ManagementException)
{
result = binder.Name switch
{
"ClassPath" or "ManagementClassPath" => obj.ClassPath,
"Path" or "ManagementPath" => obj.Path,
"Scope" or "ManagementScope" => obj.Scope,
_ => null
};
return result is not null;
}
}
/// <inheritdoc/>
public override bool TryInvokeMember(InvokeMemberBinder binder, object?[]? args, [NotNullWhen(true)] out object? result)
{
if (args?.Length == 1)
{
ManagementBaseObject? input = null;
if (args[0] is ManagementBaseObject mbo)
{
input = mbo;
}
else if (args[0] is IDictionary<string, object> eo)
{
input = obj.GetMethodParameters(binder.Name);
foreach (KeyValuePair<string, object> kv in eo)
input[kv.Key] = kv.Value;
}
else if (args[0] is (string Key, object Value)[] a)
{
input = obj.GetMethodParameters(binder.Name);
foreach ((string Key, object Value) in a)
input[Key] = Value;
}
if (input is not null)
{
result = obj.InvokeMethod(binder.Name, input, new());
return true;
}
}
try
{
result = obj.InvokeMethod(binder.Name, args!);
return true;
}
catch (ManagementException) { }
return base.TryInvokeMember(binder, args, out result);
}
/// <inheritdoc/>
public override bool TrySetMember(SetMemberBinder binder, object? value)
{
try { obj.SetPropertyValue(binder.Name, value!); return true; }
catch (ManagementException)
{
switch (binder.Name)
{
case "Path":
case "ManagementPath":
obj.Path = value as ManagementPath ?? throw new ArgumentNullException(nameof(value));
return true;
case "Scope":
case "ManagementScope":
obj.Scope = value as ManagementScope ?? throw new ArgumentNullException(nameof(value));
return true;
default:
return false;
}
}
}
}