//------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //------------------------------------------------------------ namespace Microsoft.Build.Tasks.Xaml { using System.Collections.Generic; using System; using System.Collections.ObjectModel; using System.Runtime; using System.Xaml; using XamlBuildTask; // This class is modal. The following properties are set in different modes: // Type TextValue Value ArrayContents // x:Null // x:Array x x // Known Value x x x // Unknown Value x x // // While this modality is not ideal, it's preferable to having multiple concrete classes // and requiring the user to down-cast. // However, we can't make the class mutable and expect users to maintain the modality. // So it's publicly immutable and has constructors for various modes (except for x:Null, // which the user can replicate by passing value == null and type == object). public sealed class AttributeParameterData { List arrayContents; public AttributeParameterData(XamlType type, string textValue) { ValidateType(type); if (textValue == null && type.UnderlyingType.IsValueType) { throw FxTrace.Exception.Argument("value", SR.AttributeValueNotNullable(type.UnderlyingType)); } this.Type = type; if (textValue != null) { this.Value = AttributeData.GetParameterValue(ref textValue, type); this.TextValue = textValue; } } public AttributeParameterData(XamlType type, object value) { ValidateType(type); if (value == null && type.UnderlyingType.IsValueType) { throw FxTrace.Exception.Argument("value", SR.AttributeValueNotNullable(type.UnderlyingType)); } if (value != null && !type.UnderlyingType.IsAssignableFrom(value.GetType())) { throw FxTrace.Exception.Argument("value", SR.AttributeValueNotAssignableToType(value.GetType(), type.UnderlyingType)); } this.Type = type; if (value != null) { if (type.UnderlyingType.IsArray) { Array array = (Array)value; XamlType elementType = type.SchemaContext.GetXamlType(type.UnderlyingType.GetElementType()); this.arrayContents = new List(); foreach (object item in array) { this.arrayContents.Add(new AttributeParameterData(elementType, item)); } this.IsArray = true; } else { this.Value = value; this.TextValue = AttributeData.GetParameterText(value, type); } } } public AttributeParameterData(XamlType type, IEnumerable arrayContents) { ValidateType(type); if (!type.UnderlyingType.IsArray) { throw FxTrace.Exception.Argument("type", SR.AttributeTypeIsNotArray(type)); } if (arrayContents == null) { throw FxTrace.Exception.ArgumentNull("arrayContents"); } this.Type = type; this.arrayContents = new List(arrayContents); this.IsArray = true; } internal AttributeParameterData() { TextValue = String.Empty; IsArray = false; } public string TextValue { get; internal set; } public object Value { get; internal set; } public XamlType Type { get; internal set; } public ReadOnlyCollection ArrayContents { get { return this.arrayContents == null ? null : this.arrayContents.AsReadOnly(); } } internal void AddArrayContentsEntry(AttributeParameterData arrayContentsEntry) { if (arrayContentsEntry != null) { if (this.arrayContents == null) { this.arrayContents = new List(); } this.arrayContents.Add(arrayContentsEntry); } } internal bool IsArray { get; set; } private static void ValidateType(XamlType type) { if (type == null) { throw FxTrace.Exception.ArgumentNull("type"); } if (type.IsUnknown) { throw FxTrace.Exception.Argument("type", SR.AttributeParameterTypeUnknownNoErrNum(type)); } if (!AttributeData.IsSupportedParameterType(type.UnderlyingType)) { throw FxTrace.Exception.Argument("type", SR.AttributeParamTypeNotSupportedNoErrNum(type)); } } } }