public VariantBuilderTests() { this.variantBuilder = new VariantBuilder(this.CatalogContext, this.CatalogMapper); this.variantProperties = new Dictionary <string, string>(); this.variantProperties.Add(this.Fixture.Create <string>(), this.Fixture.Create <string>()); this.variantProperties.Add(this.Fixture.Create <string>(), this.Fixture.Create <string>()); }
private Expression GenerateTryBlock() { // // Declare variables // ParameterExpression excepInfo = Expression.Variable(typeof(ExcepInfo), "excepInfo"); ParameterExpression argErr = Expression.Variable(typeof(uint), "argErr"); ParameterExpression hresult = Expression.Variable(typeof(int), "hresult"); List <Expression> tryStatements = new List <Expression>(); Expression expr; if (_keywordArgNames.Length > 0) { string[] names = _keywordArgNames.AddFirst(_methodDesc.Name); tryStatements.Add( Expression.Assign( Expression.Field( DispParamsVariable, typeof(ComTypes.DISPPARAMS).GetField("rgdispidNamedArgs") ), Expression.Call(typeof(UnsafeMethods).GetMethod("GetIdsOfNamedParameters"), DispatchObjectVariable, Expression.Constant(names), DispIdVariable, DispIdsOfKeywordArgsPinnedVariable ) ) ); } // // Marshal the arguments to Variants // // For a call like this: // comObj.Foo(100, 101, 102, x=123, z=125) // DISPPARAMS needs to be setup like this: // cArgs: 5 // cNamedArgs: 2 // rgArgs: 123, 125, 102, 101, 100 // rgdispidNamedArgs: dispid x, dispid z (the dispids of x and z respectively) Expression[] parameters = MakeArgumentExpressions(); int reverseIndex = _varEnumSelector.VariantBuilders.Length - 1; int positionalArgs = _varEnumSelector.VariantBuilders.Length - _keywordArgNames.Length; // args passed by position order and not by name for (int i = 0; i < _varEnumSelector.VariantBuilders.Length; i++, reverseIndex--) { int variantIndex; if (i >= positionalArgs) { // Named arguments are in order at the start of rgArgs variantIndex = i - positionalArgs; } else { // Positial arguments are in reverse order at the tail of rgArgs variantIndex = reverseIndex; } VariantBuilder variantBuilder = _varEnumSelector.VariantBuilders[i]; Expression marshal = variantBuilder.InitializeArgumentVariant( VariantArray.GetStructField(ParamVariantsVariable, variantIndex), parameters[i + 1] ); if (marshal != null) { tryStatements.Add(marshal); } } // // Call Invoke // ComTypes.INVOKEKIND invokeKind; if (_methodDesc.IsPropertyPut) { if (_methodDesc.IsPropertyPutRef) { invokeKind = ComTypes.INVOKEKIND.INVOKE_PROPERTYPUTREF; } else { invokeKind = ComTypes.INVOKEKIND.INVOKE_PROPERTYPUT; } } else { // INVOKE_PROPERTYGET should only be needed for COM objects without typeinfo, where we might have to treat properties as methods invokeKind = ComTypes.INVOKEKIND.INVOKE_FUNC | ComTypes.INVOKEKIND.INVOKE_PROPERTYGET; } MethodCallExpression invoke = Expression.Call( typeof(UnsafeMethods).GetMethod("IDispatchInvoke"), DispatchPointerVariable, DispIdVariable, Expression.Constant(invokeKind), DispParamsVariable, InvokeResultVariable, excepInfo, argErr ); expr = Expression.Assign(hresult, invoke); tryStatements.Add(expr); // // ComRuntimeHelpers.CheckThrowException(hresult, excepInfo, argErr, ThisParameter); // expr = Expression.Call( typeof(ComRuntimeHelpers).GetMethod("CheckThrowException"), hresult, excepInfo, argErr, Expression.Constant(_methodDesc.Name, typeof(string)) ); tryStatements.Add(expr); // // _returnValue = (ReturnType)_invokeResult.ToObject(); // Expression invokeResultObject = Expression.Call( InvokeResultVariable, typeof(Variant).GetMethod("ToObject")); VariantBuilder[] variants = _varEnumSelector.VariantBuilders; Expression[] parametersForUpdates = MakeArgumentExpressions(); tryStatements.Add(Expression.Assign(ReturnValueVariable, invokeResultObject)); for (int i = 0, n = variants.Length; i < n; i++) { Expression updateFromReturn = variants[i].UpdateFromReturn(parametersForUpdates[i + 1]); if (updateFromReturn != null) { tryStatements.Add(updateFromReturn); } } tryStatements.Add(Expression.Empty()); return(Expression.Block(new[] { excepInfo, argErr, hresult }, tryStatements)); }