Skip to content

Commit a998cbc

Browse files
daxian-dbwTylerLeonhardt
authored andcommitted
Use ConvertFromJson/ConvertToJson APIs directly (#141)
* Use ConvertFromJson/ConvertToJson APIs directly * Update the test code that uses 'ToTypedData' * Add back the processing of PSObject
1 parent 1ff1010 commit a998cbc

File tree

4 files changed

+38
-65
lines changed

4 files changed

+38
-65
lines changed

src/PowerShell/PowerShellManager.cs

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -190,18 +190,6 @@ internal Hashtable InvokeFunction(
190190
}
191191
}
192192

193-
/// <summary>
194-
/// Helper method to convert the result returned from a function to JSON.
195-
/// </summary>
196-
internal string ConvertToJson(object fromObj)
197-
{
198-
return _pwsh.AddCommand("Microsoft.PowerShell.Utility\\ConvertTo-Json")
199-
.AddParameter("InputObject", fromObj)
200-
.AddParameter("Depth", 3)
201-
.AddParameter("Compress", true)
202-
.InvokeAndClearCommands<string>()[0];
203-
}
204-
205193
private void ResetRunspace(string moduleName)
206194
{
207195
// Reset the runspace to the Initial Session State

src/RequestProcessor.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ private void ProcessInvocationRequestImpl(StreamingMessage request, AzFunctionIn
164164
? InvokeOrchestrationFunction(psManager, functionInfo, invocationRequest)
165165
: InvokeSingleActivityFunction(psManager, functionInfo, invocationRequest);
166166

167-
BindOutputFromResult(psManager, response.InvocationResponse, functionInfo, results);
167+
BindOutputFromResult(response.InvocationResponse, functionInfo, results);
168168
}
169169
catch (Exception e)
170170
{
@@ -239,7 +239,7 @@ private Hashtable InvokeSingleActivityFunction(PowerShellManager psManager, AzFu
239239
/// <summary>
240240
/// Set the 'ReturnValue' and 'OutputData' based on the invocation results appropriately.
241241
/// </summary>
242-
private void BindOutputFromResult(PowerShellManager psManager, InvocationResponse response, AzFunctionInfo functionInfo, Hashtable results)
242+
private void BindOutputFromResult(InvocationResponse response, AzFunctionInfo functionInfo, Hashtable results)
243243
{
244244
switch (functionInfo.Type)
245245
{
@@ -252,7 +252,7 @@ private void BindOutputFromResult(PowerShellManager psManager, InvocationRespons
252252

253253
object outValue = results[outBindingName];
254254
object transformedValue = Utils.TransformOutBindingValueAsNeeded(outBindingName, bindingInfo, outValue);
255-
TypedData dataToUse = transformedValue.ToTypedData(psManager);
255+
TypedData dataToUse = transformedValue.ToTypedData();
256256

257257
// if one of the bindings is '$return' we need to set the ReturnValue
258258
if(string.Equals(outBindingName, AzFunctionInfo.DollarReturn, StringComparison.OrdinalIgnoreCase))
@@ -273,7 +273,7 @@ private void BindOutputFromResult(PowerShellManager psManager, InvocationRespons
273273

274274
case AzFunctionType.OrchestrationFunction:
275275
case AzFunctionType.ActivityFunction:
276-
response.ReturnValue = results[AzFunctionInfo.DollarReturn].ToTypedData(psManager);
276+
response.ReturnValue = results[AzFunctionInfo.DollarReturn].ToTypedData();
277277
break;
278278

279279
default:

src/Utility/TypeExtensions.cs

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@
88
using System.IO;
99
using System.Linq;
1010
using System.Management.Automation;
11-
using System.Reflection;
1211

1312
using Google.Protobuf;
1413
using Microsoft.Azure.WebJobs.Script.Grpc.Messages;
1514
using Microsoft.Azure.Functions.PowerShellWorker.PowerShell;
15+
using Microsoft.PowerShell.Commands;
1616
using Newtonsoft.Json.Linq;
1717

1818
namespace Microsoft.Azure.Functions.PowerShellWorker.Utility
@@ -94,26 +94,10 @@ internal static object ToObject(this TypedData data)
9494
}
9595
}
9696

97-
// PowerShell NuGet packages only have 'System.Management.Automation.dll' as the ref assembly, and thus types from other powershell assemblies
98-
// cannot be used directly in an application that reference the PowerShell NuGet packages. This is tracked by PowerShell#8121.
99-
// Here we need to use 'Microsoft.PowerShell.Commands.JsonObject' from 'Microsoft.PowerShell.Commands.Utility'. Due the above issue, we have to
100-
// use reflection to call 'JsonObject.ConvertFromJson(...)'.
101-
private static MethodInfo s_ConvertFromJson = null;
10297
private static object ConvertFromJson(string json)
10398
{
104-
const string UtilityAssemblyFullName = "Microsoft.PowerShell.Commands.Utility, Version=6.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35";
99+
object retObj = JsonObject.ConvertFromJson(json, returnHashtable: true, error: out _);
105100

106-
if (s_ConvertFromJson == null)
107-
{
108-
Assembly utilityAssembly = AppDomain.CurrentDomain.GetAssemblies().First(asm => asm.FullName == UtilityAssemblyFullName);
109-
Type jsonObjectType = utilityAssembly.GetType("Microsoft.PowerShell.Commands.JsonObject");
110-
s_ConvertFromJson = jsonObjectType.GetMethod(
111-
name: "ConvertFromJson",
112-
types: new Type[] { typeof(string), typeof(bool), typeof(ErrorRecord).MakeByRefType() },
113-
modifiers: null);
114-
}
115-
116-
object retObj = s_ConvertFromJson.Invoke(null, new object[] { json, true, null });
117101
if (retObj is PSObject psObj)
118102
{
119103
retObj = psObj.BaseObject;
@@ -136,6 +120,16 @@ private static object ConvertFromJson(string json)
136120
return retObj;
137121
}
138122

123+
private static string ConvertToJson(object fromObj)
124+
{
125+
var context = new JsonObject.ConvertToJsonContext(
126+
maxDepth: 3,
127+
enumsAsStrings: false,
128+
compressOutput: true);
129+
130+
return JsonObject.ConvertToJson(fromObj, in context);
131+
}
132+
139133
internal static RpcException ToRpcException(this Exception exception)
140134
{
141135
return new RpcException
@@ -146,7 +140,7 @@ internal static RpcException ToRpcException(this Exception exception)
146140
};
147141
}
148142

149-
private static RpcHttp ToRpcHttp(this HttpResponseContext httpResponseContext, PowerShellManager psHelper)
143+
private static RpcHttp ToRpcHttp(this HttpResponseContext httpResponseContext)
150144
{
151145
var rpcHttp = new RpcHttp
152146
{
@@ -155,7 +149,7 @@ private static RpcHttp ToRpcHttp(this HttpResponseContext httpResponseContext, P
155149

156150
if (httpResponseContext.Body != null)
157151
{
158-
rpcHttp.Body = httpResponseContext.Body.ToTypedData(psHelper);
152+
rpcHttp.Body = httpResponseContext.Body.ToTypedData();
159153
}
160154

161155
rpcHttp.EnableContentNegotiation = httpResponseContext.EnableContentNegotiation;
@@ -178,7 +172,7 @@ private static RpcHttp ToRpcHttp(this HttpResponseContext httpResponseContext, P
178172
return rpcHttp;
179173
}
180174

181-
internal static TypedData ToTypedData(this object value, PowerShellManager psHelper)
175+
internal static TypedData ToTypedData(this object value)
182176
{
183177
if (value is TypedData self)
184178
{
@@ -218,14 +212,13 @@ internal static TypedData ToTypedData(this object value, PowerShellManager psHel
218212
typedData.Stream = ByteString.FromStream(s);
219213
break;
220214
case HttpResponseContext http:
221-
typedData.Http = http.ToRpcHttp(psHelper);
215+
typedData.Http = http.ToRpcHttp();
222216
break;
223217
case string str:
224218
if (IsValidJson(str)) { typedData.Json = str; } else { typedData.String = str; }
225219
break;
226220
default:
227-
if (psHelper == null) { throw new ArgumentNullException(nameof(psHelper)); }
228-
typedData.Json = psHelper.ConvertToJson(originalValue);
221+
typedData.Json = ConvertToJson(originalValue);
229222
break;
230223
}
231224
return typedData;

test/Unit/Utility/TypeExtensionsTests.cs

Lines changed: 17 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,8 @@ namespace Microsoft.Azure.Functions.PowerShellWorker.Test
2020
{
2121
public class TypeExtensionsTests
2222
{
23-
private readonly ConsoleLogger _testLogger;
24-
private readonly PowerShellManager _testManager;
25-
26-
public TypeExtensionsTests()
27-
{
28-
_testLogger = new ConsoleLogger();
29-
_testManager = TestUtils.NewTestPowerShellManager(_testLogger);
30-
}
31-
3223
#region TypedDataToObject
24+
3325
[Fact]
3426
public void TestTypedDataToObjectHttpRequestContextBasic()
3527
{
@@ -343,7 +335,7 @@ public void TestObjectToTypedDataRpcHttpBasic()
343335
}
344336
};
345337

346-
Assert.Equal(expected, input.ToTypedData(null));
338+
Assert.Equal(expected, input.ToTypedData());
347339
}
348340

349341
[Fact]
@@ -366,7 +358,7 @@ public void TestObjectToTypedDataRpcHttpContentTypeSet()
366358
}
367359
};
368360

369-
Assert.Equal(expected, input.ToTypedData(null));
361+
Assert.Equal(expected, input.ToTypedData());
370362
}
371363

372364
[Fact]
@@ -389,7 +381,7 @@ public void TestObjectToTypedDataRpcHttpContentTypeInHeader()
389381
}
390382
};
391383

392-
Assert.Equal(expected, input.ToTypedData(null));
384+
Assert.Equal(expected, input.ToTypedData());
393385
}
394386

395387
[Fact]
@@ -412,7 +404,7 @@ public void TestObjectToTypedDataRpcHttpStatusCodeString()
412404
}
413405
};
414406

415-
Assert.Equal(expected, input.ToTypedData(null));
407+
Assert.Equal(expected, input.ToTypedData());
416408
}
417409

418410
[Fact]
@@ -426,7 +418,7 @@ public void TestObjectToTypedDataInt()
426418
Int = data
427419
};
428420

429-
Assert.Equal(expected, input.ToTypedData(null));
421+
Assert.Equal(expected, input.ToTypedData());
430422
}
431423

432424
[Fact]
@@ -440,7 +432,7 @@ public void TestObjectToTypedDataDouble()
440432
Double = data
441433
};
442434

443-
Assert.Equal(expected, input.ToTypedData(null));
435+
Assert.Equal(expected, input.ToTypedData());
444436
}
445437

446438
[Fact]
@@ -454,7 +446,7 @@ public void TestObjectToTypedDataString()
454446
String = data
455447
};
456448

457-
Assert.Equal(expected, input.ToTypedData(null));
449+
Assert.Equal(expected, input.ToTypedData());
458450
}
459451

460452
[Fact]
@@ -468,7 +460,7 @@ public void TestObjectToTypedDataBytes()
468460
Bytes = ByteString.CopyFrom(data)
469461
};
470462

471-
Assert.Equal(expected, input.ToTypedData(null));
463+
Assert.Equal(expected, input.ToTypedData());
472464
}
473465

474466
[Fact]
@@ -483,7 +475,7 @@ public void TestObjectToTypedDataStream()
483475
Stream = ByteString.FromStream(data)
484476
};
485477

486-
Assert.Equal(expected, input.ToTypedData(null));
478+
Assert.Equal(expected, input.ToTypedData());
487479
}
488480
}
489481

@@ -498,7 +490,7 @@ public void TestObjectToTypedDataJsonString()
498490
Json = data
499491
};
500492

501-
Assert.Equal(expected, input.ToTypedData(null));
493+
Assert.Equal(expected, input.ToTypedData());
502494
}
503495

504496
[Fact]
@@ -512,7 +504,7 @@ public void TestObjectToTypedDataJsonHashtable()
512504
Json = "{\"foo\":\"bar\"}"
513505
};
514506

515-
Assert.Equal(expected, input.ToTypedData(_testManager));
507+
Assert.Equal(expected, input.ToTypedData());
516508
}
517509

518510
[Fact]
@@ -526,7 +518,7 @@ public void TestObjectToTypedData_PSObjectToJson_1()
526518
Json = "{\"foo\":\"bar\"}"
527519
};
528520

529-
Assert.Equal(expected, input.ToTypedData(_testManager));
521+
Assert.Equal(expected, input.ToTypedData());
530522
}
531523

532524
[Fact]
@@ -541,7 +533,7 @@ public void TestObjectToTypedData_PSObjectToJson_2()
541533
Json = "{\"foo\":\"bar\"}"
542534
};
543535

544-
Assert.Equal(expected, input.ToTypedData(_testManager));
536+
Assert.Equal(expected, input.ToTypedData());
545537
}
546538
}
547539

@@ -551,7 +543,7 @@ public void TestObjectToTypedData_PSObjectToBytes()
551543
var data = new byte[] { 12,23,34 };
552544
object input = PSObject.AsPSObject(data);
553545

554-
TypedData output = input.ToTypedData(_testManager);
546+
TypedData output = input.ToTypedData();
555547

556548
Assert.Equal(TypedData.DataOneofCase.Bytes, output.DataCase);
557549
Assert.Equal(3, output.Bytes.Length);
@@ -563,7 +555,7 @@ public void TestObjectToTypedData_PSObjectToStream()
563555
using (var data = new MemoryStream(new byte[] { 12,23,34 }))
564556
{
565557
object input = PSObject.AsPSObject(data);
566-
TypedData output = input.ToTypedData(_testManager);
558+
TypedData output = input.ToTypedData();
567559

568560
Assert.Equal(TypedData.DataOneofCase.Stream, output.DataCase);
569561
Assert.Equal(3, output.Stream.Length);
@@ -574,7 +566,7 @@ public void TestObjectToTypedData_PSObjectToStream()
574566
public void TestObjectToTypedData_PSObjectToString()
575567
{
576568
object input = PSObject.AsPSObject("Hello World");
577-
TypedData output = input.ToTypedData(_testManager);
569+
TypedData output = input.ToTypedData();
578570

579571
Assert.Equal(TypedData.DataOneofCase.String, output.DataCase);
580572
Assert.Equal("Hello World", output.String);

0 commit comments

Comments
 (0)