Removed DeflateStream.UnmanagedRead Read loop. Fixes #19313.
[mono.git] / mcs / class / System.Xaml / System.Xaml / XamlMember.cs
1 //
2 // Copyright (C) 2010 Novell Inc. http://novell.com
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining
5 // a copy of this software and associated documentation files (the
6 // "Software"), to deal in the Software without restriction, including
7 // without limitation the rights to use, copy, modify, merge, publish,
8 // distribute, sublicense, and/or sell copies of the Software, and to
9 // permit persons to whom the Software is furnished to do so, subject to
10 // the following conditions:
11 // 
12 // The above copyright notice and this permission notice shall be
13 // included in all copies or substantial portions of the Software.
14 // 
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 //
23 using System;
24 using System.Collections.Generic;
25 using System.ComponentModel;
26 using System.Reflection;
27 using System.Windows.Markup;
28 using System.Xaml.Schema;
29
30 namespace System.Xaml
31 {
32         public class XamlMember : IEquatable<XamlMember>
33         {
34                 public XamlMember (EventInfo eventInfo, XamlSchemaContext schemaContext)
35                         : this (eventInfo, schemaContext, null)
36                 {
37                 }
38
39                 public XamlMember (EventInfo eventInfo, XamlSchemaContext schemaContext, XamlMemberInvoker invoker)
40                         : this (schemaContext, invoker)
41                 {
42                         if (eventInfo == null)
43                                 throw new ArgumentNullException ("eventInfo");
44                         Name = eventInfo.Name;
45                         underlying_member = eventInfo;
46                         DeclaringType = schemaContext.GetXamlType (eventInfo.DeclaringType);
47                         target_type = DeclaringType;
48                         UnderlyingSetter = eventInfo.GetAddMethod ();
49                         is_event = true;
50                 }
51
52                 public XamlMember (PropertyInfo propertyInfo, XamlSchemaContext schemaContext)
53                         : this (propertyInfo, schemaContext, null)
54                 {
55                 }
56
57                 public XamlMember (PropertyInfo propertyInfo, XamlSchemaContext schemaContext, XamlMemberInvoker invoker)
58                         : this (schemaContext, invoker)
59                 {
60                         if (propertyInfo == null)
61                                 throw new ArgumentNullException ("propertyInfo");
62                         Name = propertyInfo.Name;
63                         underlying_member = propertyInfo;
64                         DeclaringType = schemaContext.GetXamlType (propertyInfo.DeclaringType);
65                         target_type = DeclaringType;
66                         UnderlyingGetter = propertyInfo.GetGetMethod (true);
67                         UnderlyingSetter = propertyInfo.GetSetMethod (true);
68                 }
69
70                 public XamlMember (string attachableEventName, MethodInfo adder, XamlSchemaContext schemaContext)
71                         : this (attachableEventName, adder, schemaContext, null)
72                 {
73                 }
74
75                 public XamlMember (string attachableEventName, MethodInfo adder, XamlSchemaContext schemaContext, XamlMemberInvoker invoker)
76                         : this (schemaContext, invoker)
77                 {
78                         if (attachableEventName == null)
79                                 throw new ArgumentNullException ("attachableEventName");
80                         if (adder == null)
81                                 throw new ArgumentNullException ("adder");
82                         Name = attachableEventName;
83                         VerifyAdderSetter (adder);
84                         underlying_member = adder;
85                         DeclaringType = schemaContext.GetXamlType (adder.DeclaringType);
86                         target_type = schemaContext.GetXamlType (typeof (object));
87                         UnderlyingSetter = adder;
88                         is_event = true;
89                         is_attachable = true;
90                 }
91
92                 public XamlMember (string attachablePropertyName, MethodInfo getter, MethodInfo setter, XamlSchemaContext schemaContext)
93                         : this (attachablePropertyName, getter, setter, schemaContext, null)
94                 {
95                 }
96
97                 public XamlMember (string attachablePropertyName, MethodInfo getter, MethodInfo setter, XamlSchemaContext schemaContext, XamlMemberInvoker invoker)
98                         : this (schemaContext, invoker)
99                 {
100                         if (attachablePropertyName == null)
101                                 throw new ArgumentNullException ("attachablePropertyName");
102                         if (getter == null && setter == null)
103                                 throw new ArgumentNullException ("getter", "Either property getter or setter must be non-null.");
104                         Name = attachablePropertyName;
105                         VerifyGetter (getter);
106                         VerifyAdderSetter (setter);
107                         underlying_member = getter ?? setter;
108                         DeclaringType = schemaContext.GetXamlType (underlying_member.DeclaringType);
109                         target_type = schemaContext.GetXamlType (typeof (object));
110                         UnderlyingGetter = getter;
111                         UnderlyingSetter = setter;
112                         is_attachable = true;
113                 }
114
115                 public XamlMember (string name, XamlType declaringType, bool isAttachable)
116                 {
117                         if (name == null)
118                                 throw new ArgumentNullException ("name");
119                         if (declaringType == null)
120                                 throw new ArgumentNullException ("declaringType");
121                         Name = name;
122                         this.invoker = new XamlMemberInvoker (this);
123                         context = declaringType.SchemaContext;
124                         DeclaringType = declaringType;
125                         target_type = DeclaringType;
126                         is_attachable = isAttachable;
127                 }
128
129                 XamlMember (XamlSchemaContext schemaContext, XamlMemberInvoker invoker)
130                 {
131                         if (schemaContext == null)
132                                 throw new ArgumentNullException ("schemaContext");
133                         context = schemaContext;
134                         this.invoker = invoker ?? new XamlMemberInvoker (this);
135                 }
136
137                 internal XamlMember (bool isDirective, string ns, string name)
138                 {
139                         directive_ns = ns;
140                         Name = name;
141                         is_directive = isDirective;
142                 }
143
144                 XamlType type, target_type;
145                 MemberInfo underlying_member;
146                 MethodInfo underlying_getter, underlying_setter;
147                 XamlSchemaContext context;
148                 XamlMemberInvoker invoker;
149                 bool is_attachable, is_event, is_directive;
150                 bool is_predefined_directive = XamlLanguage.InitializingDirectives;
151                 string directive_ns;
152
153                 internal MethodInfo UnderlyingGetter {
154                         get { return LookupUnderlyingGetter (); }
155                         private set { underlying_getter = value; }
156                 }
157                 internal MethodInfo UnderlyingSetter {
158                         get { return LookupUnderlyingSetter (); }
159                         private set { underlying_setter = value; }
160                 }
161
162                 public XamlType DeclaringType { get; private set; }
163                 public string Name { get; private set; }
164
165                 public string PreferredXamlNamespace {
166                         get { return directive_ns ?? (DeclaringType == null ? null : DeclaringType.PreferredXamlNamespace); }
167                 }
168                 
169 #if !NET_2_1
170                 public DesignerSerializationVisibility SerializationVisibility {
171                         get {
172                                 var c= GetCustomAttributeProvider ();
173                                 var a = c == null ? null : c.GetCustomAttribute<DesignerSerializationVisibilityAttribute> (false);
174                                 return a != null ? a.Visibility : DesignerSerializationVisibility.Visible;
175                         }
176                 }
177 #endif
178
179                 public bool IsAttachable {
180                         get { return is_attachable; }
181                 }
182
183                 public bool IsDirective {
184                         get { return is_directive; }
185                 }
186
187                 public bool IsNameValid {
188                         get { return XamlLanguage.IsValidXamlName (Name); }
189                 }
190
191                 public XamlValueConverter<XamlDeferringLoader> DeferringLoader {
192                         get { return LookupDeferringLoader (); }
193                 }
194                 
195                 static readonly XamlMember [] empty_members = new XamlMember [0];
196                 
197                 public IList<XamlMember> DependsOn {
198                         get { return LookupDependsOn () ?? empty_members; }
199                 }
200
201                 public XamlMemberInvoker Invoker {
202                         get { return LookupInvoker (); }
203                 }
204                 public bool IsAmbient {
205                         get { return LookupIsAmbient (); }
206                 }
207                 public bool IsEvent {
208                         get { return LookupIsEvent (); }
209                 }
210                 public bool IsReadOnly {
211                         get { return LookupIsReadOnly (); }
212                 }
213                 public bool IsReadPublic {
214                         get { return LookupIsReadPublic (); }
215                 }
216                 public bool IsUnknown {
217                         get { return LookupIsUnknown (); }
218                 }
219                 public bool IsWriteOnly {
220                         get { return LookupIsWriteOnly (); }
221                 }
222                 public bool IsWritePublic {
223                         get { return LookupIsWritePublic (); }
224                 }
225                 public XamlType TargetType {
226                         get { return LookupTargetType (); }
227                 }
228                 public XamlType Type {
229                         get { return LookupType (); }
230                 }
231                 public XamlValueConverter<TypeConverter> TypeConverter {
232                         get { return LookupTypeConverter (); }
233                 }
234                 public MemberInfo UnderlyingMember {
235                         get { return LookupUnderlyingMember (); }
236                 }
237                 public XamlValueConverter<ValueSerializer> ValueSerializer {
238                         get { return LookupValueSerializer (); }
239                 }
240
241                 public static bool operator == (XamlMember left, XamlMember right)
242                 {
243                         return IsNull (left) ? IsNull (right) : left.Equals (right);
244                 }
245
246                 static bool IsNull (XamlMember a)
247                 {
248                         return Object.ReferenceEquals (a, null);
249                 }
250
251                 public static bool operator != (XamlMember left, XamlMember right)
252                 {
253                         return !(left == right);
254                 }
255                 
256                 public override bool Equals (object other)
257                 {
258                         var x = other as XamlMember;
259                         return Equals (x);
260                 }
261                 
262                 public bool Equals (XamlMember other)
263                 {
264                         // this should be in general correct; XamlMembers are almost not comparable.
265                         if (Object.ReferenceEquals (this, other))
266                                 return true;
267                         // It does not compare XamlSchemaContext.
268                         return !IsNull (other) &&
269                                 underlying_member == other.underlying_member &&
270                                 underlying_getter == other.underlying_getter &&
271                                 underlying_setter == other.underlying_setter &&
272                                 Name == other.Name &&
273                                 PreferredXamlNamespace == other.PreferredXamlNamespace &&
274                                 directive_ns == other.directive_ns &&
275                                 is_attachable == other.is_attachable;
276                 }
277
278                 public override int GetHashCode ()
279                 {
280                         return ToString ().GetHashCode (); // should in general work.
281                 }
282
283                 [MonoTODO ("there are some patterns that return different kind of value: e.g. List<int>.Capacity")]
284                 public override string ToString ()
285                 {
286                         if (is_attachable || String.IsNullOrEmpty (PreferredXamlNamespace)) {
287                                 if (DeclaringType == null)
288                                         return Name;
289                                 else
290                                         return String.Concat (DeclaringType.UnderlyingType.FullName, ".", Name);
291                         }
292                         else
293                                 return String.Concat ("{", PreferredXamlNamespace, "}", DeclaringType.Name, ".", Name);
294                 }
295
296                 public virtual IList<string> GetXamlNamespaces ()
297                 {
298                         throw new NotImplementedException ();
299                 }
300
301                 // lookups
302
303                 internal ICustomAttributeProvider GetCustomAttributeProvider ()
304                 {
305                         return LookupCustomAttributeProvider ();
306                 }
307
308                 protected virtual ICustomAttributeProvider LookupCustomAttributeProvider ()
309                 {
310                         return UnderlyingMember;
311                 }
312
313                 protected virtual XamlValueConverter<XamlDeferringLoader> LookupDeferringLoader ()
314                 {
315                         // FIXME: use XamlDeferLoadAttribute.
316                         return null;
317                 }
318
319                 static readonly XamlMember [] empty_list = new XamlMember [0];
320
321                 protected virtual IList<XamlMember> LookupDependsOn ()
322                 {
323                         return empty_list;
324                 }
325
326                 protected virtual XamlMemberInvoker LookupInvoker ()
327                 {
328                         return invoker;
329                 }
330                 protected virtual bool LookupIsAmbient ()
331                 {
332                         var t = Type != null ? Type.UnderlyingType : null;
333                         return t != null && t.GetCustomAttributes (typeof (AmbientAttribute), false).Length > 0;
334                 }
335
336                 protected virtual bool LookupIsEvent ()
337                 {
338                         return is_event;
339                 }
340
341                 protected virtual bool LookupIsReadOnly ()
342                 {
343                         return UnderlyingGetter != null && UnderlyingSetter == null;
344                 }
345                 protected virtual bool LookupIsReadPublic ()
346                 {
347                         if (underlying_member == null)
348                                 return true;
349                         if (UnderlyingGetter != null)
350                                 return UnderlyingGetter.IsPublic;
351                         return false;
352                 }
353
354                 protected virtual bool LookupIsUnknown ()
355                 {
356                         return underlying_member == null;
357                 }
358
359                 protected virtual bool LookupIsWriteOnly ()
360                 {
361                         var pi = underlying_member as PropertyInfo;
362                         if (pi != null)
363                                 return !pi.CanRead && pi.CanWrite;
364                         return UnderlyingGetter == null && UnderlyingSetter != null;
365                 }
366
367                 protected virtual bool LookupIsWritePublic ()
368                 {
369                         if (underlying_member == null)
370                                 return true;
371                         if (UnderlyingSetter != null)
372                                 return UnderlyingSetter.IsPublic;
373                         return false;
374                 }
375
376                 protected virtual XamlType LookupTargetType ()
377                 {
378                         return target_type;
379                 }
380
381                 protected virtual XamlType LookupType ()
382                 {
383                         if (type == null)
384                                 type = context.GetXamlType (DoGetType ());
385                         return type;
386                 }
387                 
388
389                 Type DoGetType ()
390                 {
391                         var pi = underlying_member as PropertyInfo;
392                         if (pi != null)
393                                 return pi.PropertyType;
394                         var ei = underlying_member as EventInfo;
395                         if (ei != null)
396                                 return ei.EventHandlerType;
397                         if (underlying_setter != null)
398                                 return underlying_setter.GetParameters () [1].ParameterType;
399                         if (underlying_getter != null)
400                                 return underlying_getter.GetParameters () [0].ParameterType;
401                         return typeof (object);
402                 }
403
404                 protected virtual XamlValueConverter<TypeConverter> LookupTypeConverter ()
405                 {
406                         var t = Type.UnderlyingType;
407                         if (t == null)
408                                 return null;
409                         if (t == typeof (object)) // it is different from XamlType.LookupTypeConverter().
410                                 return null;
411
412                         var a = GetCustomAttributeProvider ();
413                         var ca = a != null ? a.GetCustomAttribute<TypeConverterAttribute> (false) : null;
414                         if (ca != null)
415                                 return context.GetValueConverter<TypeConverter> (System.Type.GetType (ca.ConverterTypeName), Type);
416
417                         return Type.TypeConverter;
418                 }
419
420                 protected virtual MethodInfo LookupUnderlyingGetter ()
421                 {
422                         return underlying_getter;
423                 }
424
425                 protected virtual MemberInfo LookupUnderlyingMember ()
426                 {
427                         return underlying_member;
428                 }
429
430                 protected virtual MethodInfo LookupUnderlyingSetter ()
431                 {
432                         return underlying_setter;
433                 }
434
435                 protected virtual XamlValueConverter<ValueSerializer> LookupValueSerializer ()
436                 {
437                         if (is_predefined_directive) // FIXME: this is likely a hack.
438                                 return null;
439                         if (Type == null)
440                                 return null;
441
442                         return XamlType.LookupValueSerializer (Type, LookupCustomAttributeProvider ()) ?? Type.ValueSerializer;
443                 }
444
445                 void VerifyGetter (MethodInfo method)
446                 {
447                         if (method == null)
448                                 return;
449                         if (method.GetParameters ().Length != 1 || method.ReturnType == typeof (void))
450                                 throw new ArgumentException (String.Format ("Property getter for {0} must have exactly one argument and must have non-void return type.", Name));
451                 }
452
453                 void VerifyAdderSetter (MethodInfo method)
454                 {
455                         if (method == null)
456                                 return;
457                         if (method.GetParameters ().Length != 2)
458                                 throw new ArgumentException (String.Format ("Property getter or event adder for {0} must have exactly one argument and must have non-void return type.", Name));
459                 }
460         }
461 }