**** Merged from MCS ****
[mono-project.git] / mcs / class / System.XML / System.Xml.Serialization / TypeData.cs
blob226cdc4cdf8f847d0a4c9ef0765e387d97a448b9
1 //
2 // System.Xml.Serialization.TypeData
3 //
4 // Authors:
5 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
6 // Lluis Sanchez Gual (lluis@ximian.com)
7 //
8 // (C) 2002 Ximian, Inc (http://www.ximian.com)
9 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
32 using System;
33 using System.Collections;
34 using System.Reflection;
36 namespace System.Xml.Serialization
38 internal class TypeData
40 Type type;
41 string elementName;
42 SchemaTypes sType;
43 Type listItemType;
44 string typeName;
45 string fullTypeName;
46 TypeData listItemTypeData;
47 TypeData listTypeData;
48 bool hasPublicConstructor = true;
50 public TypeData (Type type, string elementName, bool isPrimitive)
52 this.type = type;
53 this.typeName = type.Name;
54 this.fullTypeName = type.FullName.Replace ('+', '.');
56 if (isPrimitive)
57 sType = SchemaTypes.Primitive;
58 else
60 if (type.IsEnum)
61 sType = SchemaTypes.Enum;
62 else if (typeof(IXmlSerializable).IsAssignableFrom (type))
63 sType = SchemaTypes.XmlSerializable;
64 else if (typeof (System.Xml.XmlNode).IsAssignableFrom (type))
65 sType = SchemaTypes.XmlNode;
66 else if (type.IsArray || typeof(IEnumerable).IsAssignableFrom (type))
67 sType = SchemaTypes.Array;
68 else
69 sType = SchemaTypes.Class;
72 if (IsListType)
73 this.elementName = TypeTranslator.GetArrayName (ListItemTypeData.XmlType);
74 else
75 this.elementName = elementName;
77 if (sType == SchemaTypes.Array || sType == SchemaTypes.Class) {
78 hasPublicConstructor = (type.IsArray || type.GetConstructor (Type.EmptyTypes) != null || type.IsAbstract || type.IsValueType);
82 internal TypeData (string typeName, string fullTypeName, string xmlType, SchemaTypes schemaType, TypeData listItemTypeData)
84 this.elementName = xmlType;
85 this.typeName = typeName;
86 this.fullTypeName = fullTypeName.Replace ('+', '.');
87 this.listItemTypeData = listItemTypeData;
88 this.sType = schemaType;
89 this.hasPublicConstructor = true;
92 public string TypeName
94 get {
95 return typeName;
99 public string XmlType
101 get {
102 return elementName;
106 public Type Type
108 get {
109 return type;
113 public string FullTypeName
115 get {
116 return fullTypeName;
120 public SchemaTypes SchemaType
122 get {
123 return sType;
127 public bool IsListType
129 get { return SchemaType == SchemaTypes.Array; }
132 public bool IsComplexType
134 get
136 return (SchemaType == SchemaTypes.Class ||
137 SchemaType == SchemaTypes.Array ||
138 SchemaType == SchemaTypes.Enum ||
139 SchemaType == SchemaTypes.XmlNode ||
140 SchemaType == SchemaTypes.XmlSerializable );
144 public bool IsValueType
148 if (type != null) return type.IsValueType;
149 else return (sType == SchemaTypes.Primitive || sType == SchemaTypes.Enum);
153 public TypeData ListItemTypeData
157 if (listItemTypeData == null && type != null)
158 listItemTypeData = TypeTranslator.GetTypeData (ListItemType);
159 return listItemTypeData;
163 public Type ListItemType
167 if (type == null)
168 throw new InvalidOperationException ("Property ListItemType is not supported for custom types");
170 if (listItemType != null) return listItemType;
172 if (SchemaType != SchemaTypes.Array)
173 throw new InvalidOperationException (Type.FullName + " is not a collection");
174 else if (type.IsArray)
175 listItemType = type.GetElementType ();
176 else if (typeof(ICollection).IsAssignableFrom (type))
178 PropertyInfo prop = GetIndexerProperty (type);
179 if (prop == null)
180 throw new InvalidOperationException ("You must implement a default accessor on " + type.FullName + " because it inherits from ICollection");
182 return prop.PropertyType;
184 else
186 MethodInfo met = type.GetMethod ("Add");
187 if (met == null)
188 throw new InvalidOperationException ("The collection " + type.FullName + " must implement an Add method");
190 ParameterInfo[] pars = met.GetParameters();
191 if (pars.Length != 1)
192 throw new InvalidOperationException ("The Add method of the collection " + type.FullName + " must have only one parameter");
194 return pars[0].ParameterType;
197 return listItemType;
201 public TypeData ListTypeData
205 if (listTypeData != null) return listTypeData;
207 listTypeData = new TypeData (TypeName + "[]",
208 FullTypeName + "[]",
209 TypeTranslator.GetArrayName(XmlType),
210 SchemaTypes.Array, this);
212 return listTypeData;
216 public bool HasPublicConstructor
218 get { return hasPublicConstructor; }
222 public static PropertyInfo GetIndexerProperty (Type collectionType)
224 PropertyInfo[] props = collectionType.GetProperties (BindingFlags.Instance | BindingFlags.Public);
225 foreach (PropertyInfo prop in props)
227 ParameterInfo[] pi = prop.GetIndexParameters ();
228 if (pi != null && pi.Length == 1 && pi[0].ParameterType == typeof(int))
229 return prop;
231 return null;