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.Collections.Generic;5using System.Dynamic;6using System.Linq;7using System.Linq.Expressions;8using System.Management.Automation.Language;9 10namespace System.Management.Automation.ComInterop11{12 internal class DispCallableMetaObject : DynamicMetaObject13 {14 private readonly DispCallable _callable;15 16 internal DispCallableMetaObject(Expression expression, DispCallable callable)17 : base(expression, BindingRestrictions.Empty, callable)18 {19 _callable = callable;20 }21 22 public override DynamicMetaObject BindGetIndex(GetIndexBinder binder, DynamicMetaObject[] indexes)23 {24 return BindGetOrInvoke(indexes, binder.CallInfo) ??25 base.BindGetIndex(binder, indexes);26 }27 28 public override DynamicMetaObject BindInvoke(InvokeBinder binder, DynamicMetaObject[] args)29 {30 return BindGetOrInvoke(args, binder.CallInfo) ??31 base.BindInvoke(binder, args);32 }33 34 private DynamicMetaObject BindGetOrInvoke(DynamicMetaObject[] args, CallInfo callInfo)35 {36 IDispatchComObject target = _callable.DispatchComObject;37 string name = _callable.MemberName;38 39 if (target.TryGetMemberMethod(name, out ComMethodDesc method) ||40 target.TryGetMemberMethodExplicit(name, out method))41 {42 List<ParameterExpression> temps = new List<ParameterExpression>();43 List<Expression> initTemps = new List<Expression>();44 45 bool[] isByRef = ComBinderHelpers.ProcessArgumentsForCom(method, ref args, temps, initTemps);46 return BindComInvoke(method, args, callInfo, isByRef, temps, initTemps);47 }48 return null;49 }50 51 public override DynamicMetaObject BindSetIndex(SetIndexBinder binder, DynamicMetaObject[] indexes, DynamicMetaObject value)52 {53 IDispatchComObject target = _callable.DispatchComObject;54 string name = _callable.MemberName;55 56 bool holdsNull = value.Value == null && value.HasValue;57 if (target.TryGetPropertySetter(name, out ComMethodDesc method, value.LimitType, holdsNull) ||58 target.TryGetPropertySetterExplicit(name, out method, value.LimitType, holdsNull))59 {60 List<ParameterExpression> temps = new List<ParameterExpression>();61 List<Expression> initTemps = new List<Expression>();62 63 bool[] isByRef = ComBinderHelpers.ProcessArgumentsForCom(method, ref indexes, temps, initTemps);64 isByRef = isByRef.AddLast(false);65 // Convert the value to the target type66 DynamicMetaObject updatedValue = new DynamicMetaObject(67 value.CastOrConvertMethodArgument(68 value.LimitType,69 name,70 "SetIndex",71 allowCastingToByRefLikeType: false,72 temps,73 initTemps),74 value.Restrictions);75 76 var result = BindComInvoke(method, indexes.AddLast(updatedValue), binder.CallInfo, isByRef, temps, initTemps);77 78 // Make sure to return the value; some languages need it.79 return new DynamicMetaObject(80 Expression.Block(result.Expression, Expression.Convert(value.Expression, typeof(object))),81 result.Restrictions82 );83 }84 85 return base.BindSetIndex(binder, indexes, value);86 }87 88 private DynamicMetaObject BindComInvoke(ComMethodDesc method, DynamicMetaObject[] indexes, CallInfo callInfo, bool[] isByRef,89 List<ParameterExpression> temps, List<Expression> initTemps)90 {91 Expression callable = Expression;92 Expression dispCall = Helpers.Convert(callable, typeof(DispCallable));93 94 DynamicMetaObject invoke = new ComInvokeBinder(95 callInfo,96 indexes,97 isByRef,98 DispCallableRestrictions(),99 Expression.Constant(method),100 Expression.Property(101 dispCall,102 typeof(DispCallable).GetProperty(nameof(DispCallable.DispatchObject))103 ),104 method105 ).Invoke();106 107 if (temps != null && temps.Count > 0)108 {109 Expression invokeExpression = invoke.Expression;110 Expression call = Expression.Block(invokeExpression.Type, temps, initTemps.Append(invokeExpression));111 invoke = new DynamicMetaObject(call, invoke.Restrictions);112 }113 114 return invoke;115 }116 117 private BindingRestrictions DispCallableRestrictions()118 {119 Expression callable = Expression;120 121 BindingRestrictions callableTypeRestrictions = BindingRestrictions.GetTypeRestriction(callable, typeof(DispCallable));122 Expression dispCall = Helpers.Convert(callable, typeof(DispCallable));123 MemberExpression dispatch = Expression.Property(dispCall, typeof(DispCallable).GetProperty(nameof(DispCallable.DispatchComObject)));124 MemberExpression dispId = Expression.Property(dispCall, typeof(DispCallable).GetProperty(nameof(DispCallable.DispId)));125 126 BindingRestrictions dispatchRestriction = IDispatchMetaObject.IDispatchRestriction(dispatch, _callable.DispatchComObject.ComTypeDesc);127 BindingRestrictions memberRestriction = BindingRestrictions.GetExpressionRestriction(128 Expression.Equal(dispId, Expression.Constant(_callable.DispId))129 );130 131 return callableTypeRestrictions.Merge(dispatchRestriction).Merge(memberRestriction);132 }133 }134}135 