mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
This commit uses psl-monad branch source-depot 7209cb9 And corresponds to [SD:688741]
181 lines
6.1 KiB
C#
181 lines
6.1 KiB
C#
/********************************************************************++
|
|
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
--********************************************************************/
|
|
|
|
using System;
|
|
using Dbg=System.Management.Automation;
|
|
using System.Collections;
|
|
using System.Collections.ObjectModel;
|
|
using System.IO;
|
|
using System.Threading;
|
|
|
|
namespace System.Management.Automation
|
|
{
|
|
/// <summary>
|
|
/// A collection of the attributes on the PSVariable object.
|
|
/// </summary>
|
|
internal class PSVariableAttributeCollection : Collection<Attribute>
|
|
{
|
|
#region constructor
|
|
|
|
/// <summary>
|
|
/// Constructs a variable attribute collection attached to
|
|
/// the specified variable. Whenever the attributes change
|
|
/// the variable value is varified against the attribute.
|
|
/// </summary>
|
|
///
|
|
/// <param name="variable">
|
|
/// The variable that needs to be verified anytime an attribute
|
|
/// changes.
|
|
/// </param>
|
|
///
|
|
/// <exception cref="ArgumentNullException">
|
|
/// If <paramref name="variable"/> is null.
|
|
/// </exception>
|
|
///
|
|
internal PSVariableAttributeCollection(PSVariable variable)
|
|
{
|
|
if (variable == null)
|
|
{
|
|
throw PSTraceSource.NewArgumentNullException("variable");
|
|
}
|
|
|
|
this.variable = variable;
|
|
}
|
|
#endregion constructor
|
|
|
|
#region Collection overrides
|
|
|
|
/// <summary>
|
|
/// Ensures that the variable that the attribute is being added to is still
|
|
/// valid after the attribute is added.
|
|
/// </summary>
|
|
///
|
|
/// <param name="index">
|
|
/// The zero-based index at which <paramref name="item"/> should be inserted.
|
|
/// </param>
|
|
///
|
|
/// <param name="item">
|
|
/// The attribute being added to the collection.
|
|
/// </param>
|
|
///
|
|
/// <exception cref="ValidationMetadataException">
|
|
/// If the new attribute causes the variable to be in an invalid state.
|
|
/// </exception>
|
|
///
|
|
/// <exception cref="ArgumentTransformationMetadataException">
|
|
/// If the new attribute is an ArgumentTransformationAttribute and the transformation
|
|
/// fails.
|
|
/// </exception>
|
|
///
|
|
protected override void InsertItem(int index, Attribute item)
|
|
{
|
|
object variableValue = VerifyNewAttribute(item);
|
|
|
|
base.InsertItem(index, item);
|
|
|
|
variable.SetValueRaw(variableValue, true);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Ensures that the variable that the attribute is being set to is still
|
|
/// valid after the attribute is set.
|
|
/// </summary>
|
|
///
|
|
/// <param name="index">
|
|
/// The zero-based index at which <paramref name="item"/> should be set.
|
|
/// </param>
|
|
///
|
|
/// <param name="item">
|
|
/// The attribute being set in the collection.
|
|
/// </param>
|
|
///
|
|
/// <exception cref="ValidationMetadataException">
|
|
/// If the new attribute causes the variable to be in an invalid state.
|
|
/// </exception>
|
|
///
|
|
protected override void SetItem(int index, Attribute item)
|
|
{
|
|
object variableValue = VerifyNewAttribute(item);
|
|
|
|
base.SetItem(index, item);
|
|
|
|
variable.SetValueRaw(variableValue, true);
|
|
}
|
|
#endregion Collection overrides
|
|
|
|
#region private data
|
|
|
|
/// <summary>
|
|
/// Ordinarily, the collection checks/converts the value (by applying the attribute)
|
|
/// when an attribute is added. This is both slow and wrong when the attributes
|
|
/// have already been checked/applied during parameter binding. So if checking
|
|
/// has already been done, this function will add the attribute without checking
|
|
/// and possibly updating the value.
|
|
/// </summary>
|
|
/// <param name="item">The attribute to add</param>
|
|
internal void AddAttributeNoCheck(Attribute item)
|
|
{
|
|
base.InsertItem(this.Count, item);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Validates and performs any transformations that the new attribute
|
|
/// implements.
|
|
/// </summary>
|
|
///
|
|
/// <param name="item">
|
|
/// The new attribute to be added to the collection.
|
|
/// </param>
|
|
///
|
|
/// <returns>
|
|
/// The new variable value. This may change from the original value if the
|
|
/// new attribute is an ArgumentTransformationAttribute.
|
|
/// </returns>
|
|
///
|
|
private object VerifyNewAttribute(Attribute item)
|
|
{
|
|
object variableValue = variable.Value;
|
|
|
|
// Perform transformation before validating
|
|
ArgumentTransformationAttribute argumentTransformation = item as ArgumentTransformationAttribute;
|
|
if (argumentTransformation != null)
|
|
{
|
|
// Get an EngineIntrinsics instance using the context of the thread.
|
|
|
|
ExecutionContext context = Runspaces.LocalPipeline.GetExecutionContextFromTLS();
|
|
EngineIntrinsics engine = null;
|
|
|
|
if (context != null)
|
|
{
|
|
engine = context.EngineIntrinsics;
|
|
}
|
|
|
|
variableValue = argumentTransformation.Transform(engine, variableValue);
|
|
}
|
|
|
|
if (!PSVariable.IsValidValue(variableValue, item))
|
|
{
|
|
ValidationMetadataException e = new ValidationMetadataException(
|
|
"ValidateSetFailure",
|
|
null,
|
|
Metadata.InvalidMetadataForCurrentValue,
|
|
variable.Name,
|
|
((variable.Value != null) ? variable.Value.ToString() : ""));
|
|
|
|
throw e;
|
|
}
|
|
|
|
return variableValue;
|
|
}
|
|
|
|
/// <summary>
|
|
/// The variable whose value needs to be verified anytime
|
|
/// the attributes change.
|
|
/// </summary>
|
|
private PSVariable variable;
|
|
#endregion private data
|
|
}
|
|
}
|
|
|