1 //
2 // XmlTypeMapMember.cs:
3 //
4 // Author:
5 //   Lluis Sanchez Gual (lluis@ximian.com)
6 //
7 // (C) 2002, 2003 Ximian, Inc.  http://www.ximian.com
8 //
9 
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 //
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 //
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30 
31 using System;
32 using System.Collections;
33 using System.Reflection;
34 
35 namespace System.Xml.Serialization
36 {
37 	// XmlTypeMapMember
38 	// A member of a class that must be serialized
39 
40 	internal class XmlTypeMapMember
41 	{
42 		string _name;
43 		int _index;
44 		int _globalIndex = -1;
45 		int _specifiedGlobalIndex = -1;
46 		TypeData _typeData;
47 		MemberInfo _member;
48 		MemberInfo _specifiedMember;
49 		MethodInfo _shouldSerialize;
50 		object _defaultValue = System.DBNull.Value;
51 		string documentation;
52 		int _flags;
53 
54 		const int OPTIONAL = 1;
55 		const int RETURN_VALUE = 2;
56 		const int IGNORE = 4;
57 
XmlTypeMapMember()58 		public XmlTypeMapMember()
59 		{
60 		}
61 
62 		public string Name
63 		{
64 			get { return _name; }
65 			set { _name = value; }
66 		}
67 
68 		public object DefaultValue
69 		{
70 			get { return _defaultValue; }
71 			set { _defaultValue = value; }
72 		}
73 
74 		public string Documentation
75 		{
76 			set { documentation = value; }
77 			get { return documentation; }
78 		}
79 
IsReadOnly(Type type)80 		public bool IsReadOnly (Type type)
81 		{
82 			if (_member == null) InitMember (type);
83 			return (_member is PropertyInfo) && !((PropertyInfo)_member).CanWrite;
84 		}
85 
GetValue(object ob, string name)86 		public static object GetValue (object ob, string name)
87 		{
88 			MemberInfo[] mems = ob.GetType().GetMember (name, BindingFlags.Instance|BindingFlags.Public);
89 			if (mems[0] is PropertyInfo) return ((PropertyInfo)mems[0]).GetValue (ob, null);
90 			else return ((FieldInfo)mems[0]).GetValue (ob);
91 		}
92 
GetValue(object ob)93 		public object GetValue (object ob)
94 		{
95 			if (_member == null) InitMember (ob.GetType());
96 			if (_member is PropertyInfo) return ((PropertyInfo)_member).GetValue (ob, null);
97 			else return ((FieldInfo)_member).GetValue (ob);
98 		}
99 
SetValue(object ob, object value)100 		public void SetValue (object ob, object value)
101 		{
102 			if (_member == null) InitMember (ob.GetType());
103 			_typeData.ConvertForAssignment (ref value);
104 			if (_member is PropertyInfo) ((PropertyInfo)_member).SetValue (ob, value, null);
105 			else ((FieldInfo)_member).SetValue (ob, value);
106 		}
107 
SetValue(object ob, string name, object value)108 		public static void SetValue (object ob, string name, object value)
109 		{
110 			MemberInfo[] mems = ob.GetType().GetMember (name, BindingFlags.Instance|BindingFlags.Public);
111 			if (mems[0] is PropertyInfo) ((PropertyInfo)mems[0]).SetValue (ob, value, null);
112 			else ((FieldInfo)mems[0]).SetValue (ob, value);
113 		}
114 
InitMember(Type type)115 		void InitMember (Type type)
116 		{
117 			MemberInfo[] mems = type.GetMember (_name, BindingFlags.Instance|BindingFlags.Public);
118 			_member = mems[0];
119 
120 			mems = type.GetMember (_name + "Specified", BindingFlags.Instance|BindingFlags.Public);
121 			if (mems.Length > 0) _specifiedMember = mems[0];
122 			if (_specifiedMember is PropertyInfo && !((PropertyInfo) _specifiedMember).CanRead)
123 				_specifiedMember = null;
124 
125 			var method = type.GetMethod ("ShouldSerialize" + _name, BindingFlags.Instance | BindingFlags.Public, null, Type.EmptyTypes, null);
126 			if (method != null && method.ReturnType == typeof (bool) && !method.IsGenericMethod)
127 				_shouldSerialize = method;
128 		}
129 
130 		public TypeData TypeData
131 		{
132 			get { return _typeData; }
133 			set { _typeData = value; }
134 		}
135 
136 		public int Index
137 		{
138 			get { return _index; }
139 			set { _index = value; }
140 		}
141 
142 		public int GlobalIndex
143 		{
144 			get { return _globalIndex; }
145 			set { _globalIndex = value; }
146 		}
147 
148 		public int SpecifiedGlobalIndex
149 		{
150 			get { return _specifiedGlobalIndex; }
151 		}
152 
153 		public bool IsOptionalValueType
154 		{
155 			get { return (_flags & OPTIONAL) != 0; }
156 			set { _flags = value ? (_flags | OPTIONAL) : (_flags & ~OPTIONAL); }
157 		}
158 
159 		public bool IsReturnValue
160 		{
161 			get { return (_flags & RETURN_VALUE) != 0; }
162 			set { _flags = value ? (_flags | RETURN_VALUE) : (_flags & ~RETURN_VALUE); }
163 		}
164 
165 		public bool Ignore
166 		{
167 			get { return (_flags & IGNORE) != 0; }
168 			set { _flags = value ? (_flags | IGNORE) : (_flags & ~IGNORE); }
169 		}
170 
CheckOptionalValueType(Type type)171 		public void CheckOptionalValueType (Type type)
172 		{
173 			// Used when reflecting a type
174 			if (_member == null) InitMember (type);
175 			IsOptionalValueType = (_specifiedMember != null || _shouldSerialize != null);
176 		}
177 
CheckOptionalValueType(XmlReflectionMember[] members)178 		public void CheckOptionalValueType (XmlReflectionMember[] members)
179 		{
180 			// Used when reflecting a list of members (e.g. web service parameters)
181 			for (int n=0; n<members.Length; n++) {
182 				XmlReflectionMember m = members [n];
183 				if (m.MemberName == Name + "Specified" && m.MemberType == typeof(bool) && m.XmlAttributes.XmlIgnore) {
184 					IsOptionalValueType = true;
185 					_specifiedGlobalIndex = n;
186 					break;
187 				}
188 			}
189 		}
190 
191 		public bool HasSpecified {
192 			get { return _specifiedMember != null; }
193 		}
194 
195 		public bool HasShouldSerialize {
196 			get { return _shouldSerialize != null; }
197 		}
198 
GetValueSpecified(object ob)199 		public bool GetValueSpecified (object ob)
200 		{
201 			if (_specifiedGlobalIndex != -1) {
202 				object[] array = (object[])ob;
203 				return _specifiedGlobalIndex < array.Length && (bool) array [_specifiedGlobalIndex];
204 			}
205 			bool specified = true;
206 
207 			if (_specifiedMember != null) {
208 				if (_specifiedMember is PropertyInfo)
209 					specified = (bool)((PropertyInfo)_specifiedMember).GetValue (ob, null);
210 				else
211 					specified = (bool)((FieldInfo)_specifiedMember).GetValue (ob);
212 			}
213 			if (_shouldSerialize != null)
214 				specified = specified && (bool)_shouldSerialize.Invoke (ob, new object [] {});
215 
216 			return specified;
217 		}
218 
IsValueSpecifiedSettable()219 		public bool IsValueSpecifiedSettable () {
220 			if (_specifiedMember is PropertyInfo)
221 				return ((PropertyInfo) _specifiedMember).CanWrite;
222 
223 			if (_specifiedMember is FieldInfo)
224 				return ! ((FieldInfo) _specifiedMember).IsInitOnly;
225 
226 			return false;
227 		}
228 
SetValueSpecified(object ob, bool value)229 		public void SetValueSpecified (object ob, bool value)
230 		{
231 			if (_specifiedGlobalIndex != -1)
232 				((object[])ob) [_specifiedGlobalIndex] = value;
233 			else if (_specifiedMember is PropertyInfo) {
234 				if (!((PropertyInfo) _specifiedMember).CanWrite)
235 					return;
236 				((PropertyInfo)_specifiedMember).SetValue (ob, value, null);
237 			} else if (_specifiedMember is FieldInfo)
238 				((FieldInfo)_specifiedMember).SetValue (ob, value);
239 		}
240 
241 		public virtual bool RequiresNullable {
242 			get { return false; }
243 		}
244 	}
245 }
246