Fix bugs in sizing TableLayoutPanel (Xamarin bug 18638)
[mono.git] / mcs / class / System.ComponentModel.Composition / src / ComponentModel / System / ComponentModel / Composition / ReflectionModel / LazyMemberInfo.cs
1 // -----------------------------------------------------------------------\r
2 // Copyright (c) Microsoft Corporation.  All rights reserved.\r
3 // -----------------------------------------------------------------------\r
4 using System;\r
5 using System.Diagnostics.CodeAnalysis;\r
6 using System.Globalization;\r
7 using System.Linq;\r
8 using System.Reflection;\r
9 using System.Threading;\r
10 using Microsoft.Internal;\r
11 \r
12 namespace System.ComponentModel.Composition.ReflectionModel\r
13 {\r
14     public struct LazyMemberInfo\r
15     {\r
16         private readonly MemberTypes _memberType;\r
17         private MemberInfo[] _accessors;\r
18         private readonly Func<MemberInfo[]> _accessorsCreator;\r
19 \r
20         public LazyMemberInfo(MemberInfo member)\r
21         {\r
22             Requires.NotNull(member, "member");\r
23             EnsureSupportedMemberType(member.MemberType, "member");\r
24 \r
25             this._accessorsCreator = null;\r
26             this._memberType = member.MemberType;\r
27             \r
28             switch(this._memberType)\r
29             {\r
30                 case MemberTypes.Property:\r
31                     PropertyInfo property = (PropertyInfo)member;\r
32                     Assumes.NotNull(property);\r
33                     this._accessors = new MemberInfo[] { property.GetGetMethod(true), property.GetSetMethod(true) };\r
34                     break;\r
35                 case MemberTypes.Event:\r
36                     EventInfo event_ = (EventInfo)member;\r
37                     this._accessors = new MemberInfo[] { event_.GetRaiseMethod(true), event_.GetAddMethod(true), event_.GetRemoveMethod(true) };\r
38                     break;\r
39                 default:\r
40                     this._accessors = new MemberInfo[] { member };\r
41                     break;\r
42             }\r
43         }\r
44 \r
45         public LazyMemberInfo(MemberTypes memberType, params MemberInfo[] accessors)\r
46         {\r
47             EnsureSupportedMemberType(memberType, "memberType");\r
48             Requires.NotNull(accessors, "accessors");\r
49             \r
50             string errorMessage;\r
51             if (!LazyMemberInfo.AreAccessorsValid(memberType, accessors, out errorMessage))\r
52             {\r
53                 throw new ArgumentException(errorMessage, "accessors");\r
54             }\r
55 \r
56             this._memberType = memberType;\r
57             this._accessors = accessors;\r
58             this._accessorsCreator = null;\r
59         }\r
60 \r
61         public LazyMemberInfo(MemberTypes memberType, Func<MemberInfo[]> accessorsCreator)\r
62         {\r
63             EnsureSupportedMemberType(memberType, "memberType");\r
64             Requires.NotNull(accessorsCreator, "accessorsCreator");\r
65 \r
66             this._memberType = memberType;\r
67             this._accessors = null;\r
68             this._accessorsCreator = accessorsCreator;\r
69         }\r
70 \r
71         public MemberTypes MemberType\r
72         {\r
73             get { return this._memberType; }\r
74         }\r
75 \r
76         public MemberInfo[] GetAccessors()\r
77         {\r
78             if ((this._accessors == null) && (this._accessorsCreator != null))\r
79             {\r
80                 MemberInfo[] accessors = this._accessorsCreator.Invoke();\r
81 \r
82                 string errorMessage;\r
83                 if (!LazyMemberInfo.AreAccessorsValid(this.MemberType, accessors, out errorMessage))\r
84                 {\r
85                     throw new InvalidOperationException(errorMessage);\r
86                 }\r
87 \r
88                 this._accessors = accessors;\r
89             }\r
90 \r
91             return this._accessors;\r
92         }\r
93 \r
94         public override int GetHashCode()\r
95         {\r
96             if (this._accessorsCreator != null)\r
97             {\r
98                 return this.MemberType.GetHashCode() ^ this._accessorsCreator.GetHashCode();\r
99             }\r
100             else\r
101             {\r
102                 Assumes.NotNull(this._accessors);\r
103                 Assumes.NotNull(this._accessors[0]);\r
104                 return this.MemberType.GetHashCode() ^ this._accessors[0].GetHashCode();\r
105             }\r
106         }\r
107 \r
108         public override bool Equals(object obj)\r
109         {\r
110             LazyMemberInfo that = (LazyMemberInfo)obj;\r
111 \r
112             // Difefrent member types mean different members\r
113             if (this._memberType != that._memberType)\r
114             {\r
115                 return false;\r
116             }\r
117 \r
118             // if any of the lazy memebers create accessors in a delay-loaded fashion, we simply compare the creators\r
119             if ((this._accessorsCreator != null) || (that._accessorsCreator != null))\r
120             {\r
121                 return object.Equals(this._accessorsCreator, that._accessorsCreator);\r
122             }\r
123 \r
124             // we are dealing with explicitly passed accessors in both cases\r
125             Assumes.NotNull(this._accessors);\r
126             Assumes.NotNull(that._accessors);\r
127             return this._accessors.SequenceEqual(that._accessors);\r
128         }\r
129 \r
130         public static bool operator ==(LazyMemberInfo left, LazyMemberInfo right)\r
131         {\r
132             return left.Equals(right);\r
133         }\r
134 \r
135         public static bool operator !=(LazyMemberInfo left, LazyMemberInfo right)\r
136         {\r
137             return !left.Equals(right);\r
138         }\r
139 \r
140         private static void EnsureSupportedMemberType(MemberTypes memberType, string argument)\r
141         {\r
142             MemberTypes supportedTypes = MemberTypes.TypeInfo | MemberTypes.NestedType | MemberTypes.Constructor | MemberTypes.Field | MemberTypes.Method | MemberTypes.Property | MemberTypes.Event;\r
143             Requires.IsInMembertypeSet(memberType, argument, supportedTypes);\r
144         }\r
145 \r
146         private static bool AreAccessorsValid(MemberTypes memberType, MemberInfo[] accessors, out string errorMessage)\r
147         {\r
148             errorMessage = string.Empty;\r
149             if (accessors == null)\r
150             {\r
151                 errorMessage = Strings.LazyMemberInfo_AccessorsNull;\r
152                 return false;\r
153             }\r
154 \r
155             if (accessors.All(accessor => accessor == null))\r
156             {\r
157                 errorMessage = Strings.LazyMemberInfo_NoAccessors;\r
158                 return false;\r
159             }\r
160 \r
161             switch (memberType)\r
162             {\r
163                 case MemberTypes.Property:\r
164                     if (accessors.Length != 2)\r
165                     {\r
166                         errorMessage = Strings.LazyMemberInfo_InvalidPropertyAccessors_Cardinality;\r
167                         return false;\r
168                     }\r
169 \r
170                     if (accessors.Where(accessor => (accessor != null) && (accessor.MemberType != MemberTypes.Method)).Any())\r
171                     {\r
172                         errorMessage = Strings.LazyMemberinfo_InvalidPropertyAccessors_AccessorType;\r
173                         return false;\r
174                     }\r
175 \r
176                     break;\r
177 \r
178                 case MemberTypes.Event:\r
179                     if (accessors.Length != 3)\r
180                     {\r
181                         errorMessage = Strings.LazyMemberInfo_InvalidEventAccessors_Cardinality;\r
182                         return false;\r
183                     }\r
184 \r
185                     if (accessors.Where(accessor => (accessor != null) && (accessor.MemberType != MemberTypes.Method)).Any())\r
186                     {\r
187                         errorMessage = Strings.LazyMemberinfo_InvalidPropertyAccessors_AccessorType;\r
188                         return false;\r
189                     }\r
190 \r
191                     break;\r
192 \r
193                 default:\r
194                     if (\r
195                         (accessors.Length != 1) ||\r
196                         ((accessors.Length == 1) && (accessors[0].MemberType != memberType)))\r
197                     {\r
198                         errorMessage = string.Format(CultureInfo.CurrentCulture, Strings.LazyMemberInfo_InvalidAccessorOnSimpleMember, memberType);\r
199                         return false;\r
200                     }\r
201                    \r
202                     break;\r
203             }\r
204             return true;\r
205         }\r
206     }\r
207 }\r