| File: System\Windows\TemplateKey.cs | Web Access |
| Project: src\wpf\src\Microsoft.DotNet.Wpf\src\PresentationFramework\PresentationFramework.csproj (PresentationFramework) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // // Description: Base class for DataTemplateKey, TableTemplateKey. // using System.Reflection; using System.ComponentModel; using System.Windows.Markup; namespace System.Windows { /// <summary> The TemplateKey object is used as the resource key for data templates</summary> [TypeConverter(typeof(TemplateKeyConverter))] public abstract class TemplateKey : ResourceKey, ISupportInitialize { /// <summary> Constructor (called by derived classes only) </summary> protected TemplateKey(TemplateType templateType) { _dataType = null; // still needs to be initialized _templateType = templateType; } /// <summary> Constructor (called by derived classes only) </summary> protected TemplateKey(TemplateType templateType, object dataType) { Exception ex = ValidateDataType(dataType, "dataType"); if (ex != null) throw ex; _dataType = dataType; _templateType = templateType; } #region ISupportInitialize /// <summary>Begin Initialization</summary> void ISupportInitialize.BeginInit() { _initializing = true; } /// <summary>End Initialization, verify that internal state is consistent</summary> void ISupportInitialize.EndInit() { if (_dataType == null) { throw new InvalidOperationException(SR.Format(SR.PropertyMustHaveValue, "DataType", this.GetType().Name)); } _initializing = false; } #endregion ISupportInitialize /// <summary> /// The type for which the template is designed. This is either /// a Type (for object data), or a string (for XML data). In the latter /// case the string denotes the XML tag name. /// </summary> public object DataType { get { return _dataType; } set { if (!_initializing) throw new InvalidOperationException(SR.Format(SR.PropertyIsInitializeOnly, "DataType", this.GetType().Name)); if (_dataType != null && value != _dataType) throw new InvalidOperationException(SR.Format(SR.PropertyIsImmutable, "DataType", this.GetType().Name)); Exception ex = ValidateDataType(value, "value"); if (ex != null) throw ex; _dataType = value; } } /// <summary> Override of Object.GetHashCode() </summary> public override int GetHashCode() { // note that the hash code can change, but only during intialization // and only once (DataType can only be changed once, from null to // non-null, and that can only happen during [Begin/End]Init). // Technically this is still a violation of the "constant during // lifetime" rule, however in practice this is acceptable. It is // very unlikely that someone will put a TemplateKey into a hashtable // before it is initialized. int hashcode = (int)_templateType; if (_dataType != null) { hashcode += _dataType.GetHashCode(); } return hashcode; } /// <summary> Override of Object.Equals() </summary> public override bool Equals(object o) { TemplateKey key = o as TemplateKey; if (key != null) { return _templateType == key._templateType && Object.Equals(_dataType, key._dataType); } return false; } /// <summary> Override of Object.ToString() </summary> public override string ToString() { Type type = DataType as Type; return (DataType != null) ? string.Create(TypeConverterHelper.InvariantEnglishUS, $"{this.GetType().Name}({DataType})") : string.Create(TypeConverterHelper.InvariantEnglishUS, $"{this.GetType().Name}(null)"); } /// <summary> /// Allows SystemResources to know which assembly the template might be defined in. /// </summary> public override Assembly Assembly { get { Type type = _dataType as Type; if (type != null) { return type.Assembly; } return null; } } /// <summary> The different types of templates that use TemplateKey </summary> protected enum TemplateType { /// <summary> DataTemplate </summary> DataTemplate, /// <summary> TableTemplate </summary> TableTemplate, } // Validate against these rules // 1. dataType must not be null (except at initialization, which is tested at EndInit) // 2. dataType must be either a Type (object data) or a string (XML tag name) // 3. dataType cannot be typeof(Object) internal static Exception ValidateDataType(object dataType, string argName) { Exception result = null; if (dataType == null) { result = new ArgumentNullException(argName); } else if (!(dataType is Type) && !(dataType is String)) { result = new ArgumentException(SR.Format(SR.MustBeTypeOrString, dataType.GetType().Name), argName); } else if (typeof(Object).Equals(dataType)) { result = new ArgumentException(SR.DataTypeCannotBeObject, argName); } return result; } private object _dataType; private TemplateType _templateType; private bool _initializing; } }