389657a9c0d6ded6575afa13b6eaa0dd91aa340b
[mono.git] / mcs / class / System.XML / System.Xml.Serialization / TypeData.cs
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 //
10
11 using System;
12 using System.Collections;
13 using System.Reflection;
14
15 namespace System.Xml.Serialization
16 {
17         internal class TypeData
18         {
19                 Type type;
20                 string elementName;
21                 SchemaTypes sType;
22                 Type listItemType;
23                 string typeName;
24                 string fullTypeName;
25                 TypeData listItemTypeData;
26                 TypeData listTypeData;
27
28                 public TypeData (Type type, string elementName, bool isPrimitive)
29                 {
30                         this.type = type;
31                         this.elementName = elementName;
32                         this.typeName = type.Name;
33                         this.fullTypeName = type.FullName;
34
35                         if (isPrimitive)
36                                 sType = SchemaTypes.Primitive;
37                         else
38                         {
39                                 if (type.IsEnum)
40                                         sType = SchemaTypes.Enum;
41                                 else if (typeof(IXmlSerializable).IsAssignableFrom (type))
42                                         sType = SchemaTypes.XmlSerializable;
43                                 else if (typeof (System.Xml.XmlNode).IsAssignableFrom (type))
44                                         sType = SchemaTypes.XmlNode;
45                                 else if (type.IsArray || typeof(IEnumerable).IsAssignableFrom (type))
46                                         sType = SchemaTypes.Array;
47                                 else
48                                         sType = SchemaTypes.Class;
49                         }
50                 }
51
52                 internal TypeData (string typeName, string fullTypeName, string xmlType, SchemaTypes schemaType, TypeData listItemTypeData)
53                 {
54                         this.elementName = xmlType;
55                         this.typeName = typeName;
56                         this.fullTypeName = fullTypeName;
57                         this.listItemTypeData = listItemTypeData;
58                         this.sType = schemaType;
59                 }
60
61                 public string TypeName
62                 {
63                         get {
64                                 return typeName;
65                         }
66                 }
67                                 
68                 public string XmlType
69                 {
70                         get {
71                                 return elementName;
72                         }
73                 }
74                                 
75                 public Type Type
76                 {
77                         get {
78                                 return type;
79                         }
80                 }
81                                 
82                 public string FullTypeName
83                 {
84                         get {
85 //                              return type.FullName.Replace ('+', '.');
86                                 return fullTypeName;
87                         }
88                 }
89
90                 public SchemaTypes SchemaType
91                 {
92                         get {
93                                 return sType;
94                         }
95                 }
96
97                 public bool IsListType
98                 {
99                         get { return SchemaType == SchemaTypes.Array; }
100                 }
101
102                 public bool IsComplexType
103                 {
104                         get 
105                         { 
106                                 return (SchemaType == SchemaTypes.Class || 
107                                               SchemaType == SchemaTypes.Array ||
108                                               SchemaType == SchemaTypes.Enum ||
109                                                   SchemaType == SchemaTypes.XmlSerializable ); 
110                         }
111                 }
112
113
114                 public TypeData ListItemTypeData
115                 {
116                         get
117                         {
118                                 if (listItemTypeData == null && type != null)
119                                         listItemTypeData = TypeTranslator.GetTypeData (ListItemType);
120                                 return listItemTypeData;
121                         }
122                 }
123                 
124                 public Type ListItemType
125                 {
126                         get
127                         {
128                                 if (type == null) throw new InvalidOperationException ("Property ListItemType is not supported for custom types");
129
130                                 if (listItemType != null) return listItemType;
131
132                                 if (SchemaType != SchemaTypes.Array)
133                                         throw new InvalidOperationException (Type.FullName + " is not a collection");
134                                 else if (type.IsArray) 
135                                         listItemType = type.GetElementType ();
136                                 else if (typeof(ICollection).IsAssignableFrom (type))
137                                 {
138                                         PropertyInfo prop = GetIndexerProperty (type);
139                                         if (prop == null) throw new InvalidOperationException ("You must implement a default accessor on " + type.FullName + " because it inherits from ICollection");
140                                         return prop.PropertyType;
141                                 }
142                                 else
143                                         return type.GetMethod ("Add").GetParameters()[0].ParameterType;
144
145                                 return listItemType;
146                         }
147                 }
148
149                 public TypeData ListTypeData
150                 {
151                         get
152                         {
153                                 if (listTypeData != null) return listTypeData;
154                                 
155                                 listTypeData = new TypeData (TypeName + "[]",
156                                         FullTypeName + "[]",
157                                         TypeTranslator.GetArrayName(XmlType),
158                                         SchemaTypes.Array, this);
159
160                                 return listTypeData;
161                         }
162                 }
163
164
165                 public static PropertyInfo GetIndexerProperty (Type collectionType)
166                 {
167                         PropertyInfo[] props = collectionType.GetProperties (BindingFlags.Instance | BindingFlags.Public);
168                         foreach (PropertyInfo prop in props)
169                         {
170                                 ParameterInfo[] pi = prop.GetIndexParameters ();
171                                 if (pi != null && pi.Length == 1 && pi[0].ParameterType == typeof(int))
172                                         return prop;
173                         }
174                         return null;
175                 }
176         }
177 }
178