[corlib] Avoid unnecessary ephemeron array resizes
[mono.git] / mcs / class / referencesource / System.Activities.Presentation / System.Activities.Presentation / System / Activities / Presentation / Base / Interaction / Model / ModelProperty.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="ModelProperty.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //------------------------------------------------------------------------------
6
7 namespace System.Activities.Presentation.Model {
8
9     using System.Activities.Presentation.Internal.Properties;
10     using System;
11     using System.ComponentModel;
12     using System.Diagnostics.CodeAnalysis;
13     using System.Globalization;
14     using System.Runtime;
15
16     /// <summary>
17     /// An ModelProperty represents a property on an item.  ModelProperties are 
18     /// associated with an instance of an item, which allows them to have simple 
19     /// Value get/set properties instead of the more cumbersome GetValue/SetValue 
20     /// mechanism of PropertyDescriptor.
21     /// 
22     /// A ModelProperty\92s value may come from a locally set value, or it may be 
23     /// inherited from somewhere higher up in the property mechanism.  Because 
24     /// all items in the tree contain Source properties, you can 
25     /// easily find out the real source of a property value simply using the 
26     /// following code:
27     /// 
28     ///     Console.WriteLine(property.Value.Source);
29     /// 
30     /// Value will return null if the property is not set anywhere in the hierarchy.
31     /// 
32     /// Type converters and editors defined on the underlying data model are 
33     /// wrapped so that they accept ModelItems as parameters.
34     /// </summary>
35     public abstract class ModelProperty {
36
37         /// <summary>
38         /// Creates a new ModelProperty.
39         /// </summary>
40         protected ModelProperty() { }
41
42         /// <summary>
43         /// Returns the attributes declared on this property.
44         /// </summary>
45         public abstract AttributeCollection Attributes { get; }
46
47         /// <summary>
48         /// Returns Value cast as a ModelItemCollection.  This property allows you to 
49         /// access collection properties easily without cluttering your code with casts:
50         /// 
51         ///     Property.Collection.Add(myItem);
52         /// 
53         /// If the property value is not a collection, this property will return null.
54         /// </summary>
55         [Fx.Tag.KnownXamlExternalAttribute]
56         public abstract ModelItemCollection Collection { get; }
57
58         /// <summary>
59         /// Returns the currently computed value for this property.  Setting a value
60         /// on this property is the same as calling SetValue, but can be used in
61         /// data binding expressions.
62         /// </summary>
63         public abstract object ComputedValue { get; set; }
64
65         /// <summary>
66         /// Returns the type converter to use with this property.  Underlying type 
67         /// converters are all wrapped so they accept Item objects.  When performing 
68         /// a conversion to a particular value, the type converter\92s return type is 
69         /// not wrapped.  Type converters which return standard values also return 
70         /// values as Item objects.
71         /// </summary>
72         public abstract TypeConverter Converter { get; }
73
74         /// <summary>
75         /// Returns the type which defines this property if IsAttached returns true.
76         /// Otherwhise, returns null.
77         /// </summary>
78         public abstract Type AttachedOwnerType { get; }
79
80         /// <summary>
81         /// Returns the default value for this property.  If the property does not 
82         /// define a default value this will return null.
83         /// </summary>
84         public abstract object DefaultValue { get; }
85
86         /// <summary>
87         /// Returns Value cast as a ItemDictionary.  This property allows you to 
88         /// access dictionary properties easily without cluttering your code with casts:
89         /// 
90         ///     Property.Dictionary[key] = value;
91         /// 
92         /// If the property value is not a dictionary, this property will return null.
93         /// </summary>
94         [Fx.Tag.KnownXamlExternalAttribute]
95         public abstract ModelItemDictionary Dictionary { get; }
96
97         /// <summary>
98         /// Returns true if the property can be shown in a property window.
99         /// </summary>
100         public abstract bool IsBrowsable { get; }
101
102         /// <summary>
103         /// Returns true if the value contained in the property is a ItemCollection.
104         /// </summary>
105         public abstract bool IsCollection { get; }
106
107         /// <summary>
108         /// Returns true if the value contained in the property is a ItemDictionary.
109         /// </summary>
110         public abstract bool IsDictionary { get; }
111
112         /// <summary>
113         /// Returns true if the property is read only.
114         /// </summary>
115         public abstract bool IsReadOnly { get; }
116
117         /// <summary>
118         /// Returns true if the property\92s value is set locally.
119         /// </summary>
120         public abstract bool IsSet { get; }
121
122         /// <summary>
123         /// Returns true if the property represents an attached property from a different type.
124         /// </summary>
125         public abstract bool IsAttached { get; }
126
127         /// <summary>
128         /// Returns the value set into this property.  A property may return a 
129         /// value that is inherited further up the element hierarchy, in which 
130         /// case this property will return a value whose source != this.  
131         /// If no value has ever been set for the property Value will return null.
132         /// </summary>
133         public abstract ModelItem Value { get; }
134
135         /// <summary>
136         /// Returns the name of this property.
137         /// </summary>
138         public abstract string Name { get; }
139
140         /// <summary>
141         /// Returns the parent of this property.  All properties have 
142         /// parents, so this never returns null.
143         /// </summary>
144         public abstract ModelItem Parent { get; }
145
146         /// <summary>
147         /// The data type of the property.
148         /// </summary>
149         public abstract Type PropertyType { get; }
150
151         /// <summary>
152         /// Clears the local value for the property.
153         /// </summary>
154         public abstract void ClearValue();
155
156         /// <summary>
157         /// Sets a local value on a property.  If this value is already 
158         /// a ModelItem, it will be used directly.  If it isn\92t, a ModelItem 
159         /// will be created.  Setting null into a property is valid, but 
160         /// this is not the same as calling ClearValue().
161         /// </summary>
162         /// <param name="value">
163         /// The new value to set.
164         /// </param>
165         /// <returns>
166         /// The input value, if the value is already a ModelItem, or a newly
167         /// created ModelItem wrapping the value.
168         /// </returns>
169         public abstract ModelItem SetValue(object value);
170
171         internal virtual string Reference
172         {
173             get
174             {
175                 return null;
176             }
177         }
178
179         internal virtual void ClearReference()
180         {
181         }
182
183         internal virtual void SetReference(string sourceProperty)
184         {
185         }
186
187         /// <summary>
188         /// Equality operator.
189         /// </summary>
190         // FXCop: args are validated; fxcop does not seem to understand ReferenceEquals.
191         
192         public static bool operator ==(ModelProperty first, ModelProperty second) {
193             if (object.ReferenceEquals(first, second)) return true;
194             if (object.ReferenceEquals(first, null) || object.ReferenceEquals(second, null)) return false;
195             return (first.Parent == second.Parent && first.Name.Equals(second.Name));
196         }
197
198         /// <summary>
199         /// Inequality operator.
200         /// </summary>
201         // FXCop: args are validated; fxcop does not seem to understand ReferenceEquals.
202         
203         public static bool operator !=(ModelProperty first, ModelProperty second) {
204             if (object.ReferenceEquals(first, second)) return false;
205             if (object.ReferenceEquals(first, null) || object.ReferenceEquals(second, null)) return true;
206             return (first.Parent != second.Parent || !first.Name.Equals(second.Name));
207         }
208
209         /// <summary>
210         /// Equality for properties.  Properties are equal if
211         /// they have the same name and parent.
212         /// </summary>
213         /// <param name="obj"></param>
214         /// <returns></returns>
215         public override bool Equals(object obj) {
216             if (object.ReferenceEquals(obj, this)) return true;
217             ModelProperty prop = obj as ModelProperty;
218             if (object.ReferenceEquals(prop, null)) return false;
219             if (prop.Parent != Parent) return false;
220             return prop.Name.Equals(Name);
221         }
222
223         /// <summary>
224         /// Standard hashcode implementation.
225         /// </summary>
226         /// <returns></returns>
227         public override int GetHashCode() {
228             return Parent.GetHashCode() ^ Name.GetHashCode();
229         }
230     }
231 }