MegaBites-AI/Windows-powershell
0372
1// Licensed to the .NET Foundation under one or more agreements.2// The .NET Foundation licenses this file to you under the MIT license.3 4using System;5using System.Collections.Generic;6using System.Diagnostics;7using System.Dynamic;8using System.Linq.Expressions;9using System.Reflection;10using System.Runtime.InteropServices;11 12namespace System.Management.Automation.ComInterop13{14 /// <summary>15 /// The ComObject class wraps a runtime-callable-wrapper and enables it to be used with the Dynamic Language Runtime and the C# dynamic keyword.16 /// </summary>17 internal class ComObject : IDynamicMetaObjectProvider18 {19 internal ComObject(object rcw)20 {21 Debug.Assert(ComBinder.IsComObject(rcw));22 RuntimeCallableWrapper = rcw;23 }24 25 internal object RuntimeCallableWrapper { get; }26 27 private static readonly object s_comObjectInfoKey = new object();28 29 /// <summary>30 /// Gets a <see cref="ComObject"/> that wraps the runtime-callable-wrapper, or creates one if none currently exists.31 /// </summary>32 /// <returns></returns>33 public static ComObject ObjectToComObject(object rcw)34 {35 Debug.Assert(ComBinder.IsComObject(rcw));36 37 object data = Marshal.GetComObjectData(rcw, s_comObjectInfoKey);38 if (data != null)39 {40 return (ComObject)data;41 }42 43 lock (s_comObjectInfoKey)44 {45 data = Marshal.GetComObjectData(rcw, s_comObjectInfoKey);46 if (data != null)47 {48 return (ComObject)data;49 }50 51 ComObject comObjectInfo = CreateComObject(rcw);52 if (!Marshal.SetComObjectData(rcw, s_comObjectInfoKey, comObjectInfo))53 {54 throw Error.SetComObjectDataFailed();55 }56 57 return comObjectInfo;58 }59 }60 61 // Expression that unwraps ComObject62 internal static MemberExpression RcwFromComObject(Expression comObject)63 {64 Debug.Assert(comObject != null && (typeof(ComObject).IsAssignableFrom(comObject.Type) || comObject.Type == typeof(object)), "must be ComObject");65 66 return Expression.Property(67 Helpers.Convert(comObject, typeof(ComObject)),68 typeof(ComObject).GetProperty(nameof(RuntimeCallableWrapper), BindingFlags.NonPublic | BindingFlags.Instance)69 );70 }71 72 // Expression that finds or creates a ComObject that corresponds to given Rcw73 internal static MethodCallExpression RcwToComObject(Expression rcw)74 {75 return Expression.Call(76 typeof(ComObject).GetMethod(nameof(ObjectToComObject)),77 Helpers.Convert(rcw, typeof(object))78 );79 }80 81 private static ComObject CreateComObject(object rcw)82 {83 if (rcw is IDispatch dispatchObject)84 {85 // We can do method invocations on IDispatch objects86 return new IDispatchComObject(dispatchObject);87 }88 89 // There is not much we can do in this case90 return new ComObject(rcw);91 }92 93 internal virtual IList<string> GetMemberNames(bool dataOnly)94 {95 return Array.Empty<string>();96 }97 98 internal virtual IList<KeyValuePair<string, object>> GetMembers(IEnumerable<string> names)99 {100 return Array.Empty<KeyValuePair<string, object>>();101 }102 103 DynamicMetaObject IDynamicMetaObjectProvider.GetMetaObject(Expression parameter)104 {105 return new ComFallbackMetaObject(parameter, BindingRestrictions.Empty, this);106 }107 }108}109 