7
// Copyright (C) 2005 Novell, Inc (http://www.novell.com)
9
// Permission is hereby granted, free of charge, to any person obtaining
10
// a copy of this software and associated documentation files (the
11
// "Software"), to deal in the Software without restriction, including
12
// without limitation the rights to use, copy, modify, merge, publish,
13
// distribute, sublicense, and/or sell copies of the Software, and to
14
// permit persons to whom the Software is furnished to do so, subject to
15
// the following conditions:
17
// The above copyright notice and this permission notice shall be
18
// included in all copies or substantial portions of the Software.
20
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30
using System.Reflection;
32
namespace MonoDevelop.Core.Serialization
34
public class ItemProperty
43
bool expandedCollection;
44
ICollectionHandler expandedCollectionHandler;
52
public ItemProperty ()
56
public ItemProperty (string name, Type propType)
59
this.propType = propType;
65
if (name.IndexOf ('/') != -1) {
66
nameList = name.Split ('/');
70
internal void SetContext (DataContext ctx)
73
if (dataType == null) {
74
if (propType == null) throw new InvalidOperationException ("Property type not specified");
75
dataType = ctx.GetConfigurationDataType (propType);
79
internal void Initialize (object[] attributes, string scope)
81
mapData = dataType.GetMapData (attributes, scope);
84
internal MemberInfo Member {
85
get { return member; }
86
set { CheckReadOnly (); member = value; }
89
internal virtual string MemberName {
90
get { return member != null ? member.Name : null; }
95
set { CheckReadOnly (); name = value; BuildNameList (); }
98
public object DefaultValue {
100
// Workaround for a bug in mono 1.0 (enum values are encoded as ints in attributes)
101
if (defaultValue != null && propType != null && propType.IsEnum && !(propType.IsInstanceOfType (defaultValue)))
102
defaultValue = Enum.ToObject (propType, defaultValue);
105
set { CheckReadOnly (); defaultValue = value; }
108
public Type PropertyType {
109
get { return propType; }
110
set { CheckReadOnly (); propType = value; }
113
public bool ExpandedCollection {
114
get { return expandedCollection; }
115
set { expandedCollection = value; }
118
internal ICollectionHandler ExpandedCollectionHandler {
119
get { return expandedCollectionHandler; }
120
set { expandedCollectionHandler = value; }
123
public bool ReadOnly {
124
get { return readOnly; }
125
set { readOnly = value; }
128
public bool WriteOnly {
129
get { return writeOnly; }
130
set { writeOnly = value; }
133
public DataType DataType {
134
get { return dataType; }
135
set { CheckReadOnly (); dataType = value; }
138
public bool SkipEmpty { get; set; }
140
public bool IsExtendedProperty (Type forType)
145
return !member.DeclaringType.IsAssignableFrom (forType);
148
internal string[] NameList {
149
get { return nameList; }
152
internal bool IsNested {
153
get { return nameList != null; }
156
internal string SingleName {
157
get { return nameList != null ? nameList [nameList.Length-1] : name; }
160
internal DataContext Context {
164
internal virtual object GetValue (object obj)
166
if (member != null) {
167
FieldInfo field = member as FieldInfo;
168
if (field != null) return field.GetValue (obj);
169
else return ((PropertyInfo)member).GetValue (obj, null);
170
} else if (obj is IExtendedDataItem) {
171
IExtendedDataItem eitem = (IExtendedDataItem) obj;
172
if (initValue == null)
173
return eitem.ExtendedProperties [Name];
175
if (!eitem.ExtendedProperties.Contains (Name))
178
return eitem.ExtendedProperties [Name];
181
else if (initValue != null)
184
throw new InvalidOperationException ("Invalid object property: " + obj.GetType() + "." + Name);
187
internal virtual void SetValue (object obj, object value)
189
if (member != null) {
190
FieldInfo field = member as FieldInfo;
192
field.SetValue (obj, value);
194
PropertyInfo pi = member as PropertyInfo;
195
pi.SetValue (obj, value, null);
198
else if (obj is IExtendedDataItem)
199
((IExtendedDataItem)obj).ExtendedProperties [Name] = value;
200
else if (initValue == null)
201
throw new InvalidOperationException ("Invalid object property: " + obj.GetType() + "." + Name);
204
internal bool HasSetter {
205
get { return member == null || (member is FieldInfo) || ((member is PropertyInfo) && ((PropertyInfo)member).CanWrite); }
208
internal bool Unsorted {
217
public bool IsExternal {
226
public object InitValue {
235
internal bool CanSerialize (SerializationContext serCtx, object instance)
237
return serCtx.Serializer.CanSerializeProperty (this, serCtx, instance);
240
internal DataNode Serialize (SerializationContext serCtx, object instance, object value)
242
return serCtx.Serializer.OnSerializeProperty (this, serCtx, instance, value);
245
internal DataNode OnSerialize (SerializationContext serCtx, object value)
247
DataNode data = dataType.Serialize (serCtx, mapData, value);
250
// Don't write empty collections or empty objects with the SkipEmpty flag
251
if (data is DataItem && !((DataItem)data).HasItemData && (DataType is CollectionDataType || SkipEmpty))
253
data.Name = SingleName;
258
internal bool CanDeserialize (SerializationContext serCtx, object instance)
260
return serCtx.Serializer.CanDeserializeProperty (this, serCtx, instance);
263
internal object Deserialize (SerializationContext serCtx, object instance, DataNode data)
265
return serCtx.Serializer.OnDeserializeProperty (this, serCtx, instance, data);
268
internal object OnDeserialize (SerializationContext serCtx, DataNode data)
270
return dataType.Deserialize (serCtx, mapData, data);
273
internal void Deserialize (SerializationContext serCtx, object instance, DataNode data, object valueInstance)
275
serCtx.Serializer.OnDeserializeProperty (this, serCtx, instance, data, valueInstance);
278
internal void OnDeserialize (SerializationContext serCtx, DataNode data, object valueInstance)
280
dataType.Deserialize (serCtx, mapData, data, valueInstance);
283
void CheckReadOnly ()
286
throw new InvalidOperationException ("Property can't be modified, it is already bound to a configuration context");