Skip to content

Investigate using LanguagePrimitives.ConvertTo rather than the converter attribute #1579

Open
@rjmholt

Description

@rjmholt

In the debugger code we currently go to great lengths to find and execute a type conversion attribute on variables:

// We have the PSVariable object for the variable the user wants to set and an object to assign to that variable.
// The last step is to determine whether the PSVariable is "strongly typed" which may require a conversion.
// If it is not strongly typed, we simply assign the object directly to the PSVariable potentially changing its type.
// Turns out ArgumentTypeConverterAttribute is not public. So we call the attribute through it's base class -
// ArgumentTransformationAttribute.
var argTypeConverterAttr =
psVariable.Attributes
.OfType<ArgumentTransformationAttribute>()
.FirstOrDefault(a => a.GetType().Name.Equals("ArgumentTypeConverterAttribute"));
if (argTypeConverterAttr != null)
{
// PSVariable is strongly typed. Need to apply the conversion/transform to the new value.
psCommand.Commands.Clear();
psCommand = new PSCommand();
psCommand.AddCommand(@"Microsoft.PowerShell.Utility\Get-Variable");
psCommand.AddParameter("Name", "ExecutionContext");
psCommand.AddParameter("ValueOnly");
errorMessages.Clear();
var getExecContextResults =
await this.powerShellContext.ExecuteCommandAsync<object>(
psCommand,
errorMessages,
sendErrorToHost: false).ConfigureAwait(false);
EngineIntrinsics executionContext = getExecContextResults.OfType<EngineIntrinsics>().FirstOrDefault();
var msg = $"Setting variable '{name}' using conversion to value: {psobject ?? "<null>"}";
this.logger.LogTrace(msg);
psVariable.Value = argTypeConverterAttr.Transform(executionContext, psobject);
}

Most of this can't be avoided, but one thing we do here is use the EngineIntrinsics value to execute the conversion attribute on the pipeline thread, which means we need to contend for and wait on a pipeline thread execution.

Instead of this, we could maybe call LanguagePrimitives.ConvertTo() with the known target type and ideally not need to use the pipeline thread.

This might not be possible, but is worth investigating...

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions