using System; using System.Reflection; namespace FullSerializer.Internal { /// /// A property or field on a MetaType. This unifies the FieldInfo and PropertyInfo classes. /// public class fsMetaProperty { internal fsMetaProperty(fsConfig config, FieldInfo field) { _memberInfo = field; StorageType = field.FieldType; MemberName = field.Name; IsPublic = field.IsPublic; IsReadOnly = field.IsInitOnly; CanRead = true; CanWrite = true; CommonInitialize(config); } internal fsMetaProperty(fsConfig config, PropertyInfo property) { _memberInfo = property; StorageType = property.PropertyType; MemberName = property.Name; IsPublic = (property.GetGetMethod() != null && property.GetGetMethod().IsPublic) && (property.GetSetMethod() != null && property.GetSetMethod().IsPublic); IsReadOnly = false; CanRead = property.CanRead; CanWrite = property.CanWrite; CommonInitialize(config); } private void CommonInitialize(fsConfig config) { var attr = fsPortableReflection.GetAttribute(_memberInfo); if (attr != null) { JsonName = attr.Name; OverrideConverterType = attr.Converter; } if (string.IsNullOrEmpty(JsonName)) { JsonName = config.GetJsonNameFromMemberName(MemberName, _memberInfo); } } /// /// Internal handle to the reflected member. /// private MemberInfo _memberInfo; /// /// The type of value that is stored inside of the property. For example, for an int field, /// StorageType will be typeof(int). /// public Type StorageType { get; private set; } /// /// A custom fsBaseConverter instance to use for this field/property, if requested. This will be /// null if the default converter selection algorithm should be used. This is specified using the /// [fsObject] annotation with the Converter field. /// public Type OverrideConverterType { get; private set; } /// /// Can this property be read? /// public bool CanRead { get; private set; } /// /// Can this property be written to? /// public bool CanWrite { get; private set; } /// /// The serialized name of the property, as it should appear in JSON. /// public string JsonName { get; private set; } /// /// The name of the actual member. /// public string MemberName { get; private set; } /// /// Is this member public? /// public bool IsPublic { get; private set; } /// /// Is this type readonly? We can modify readonly properties using reflection, but not /// using generated C#. /// public bool IsReadOnly { get; private set; } /// /// Writes a value to the property that this MetaProperty represents, using given object /// instance as the context. /// public void Write(object context, object value) { FieldInfo field = _memberInfo as FieldInfo; PropertyInfo property = _memberInfo as PropertyInfo; if (field != null) { field.SetValue(context, value); } else if (property != null) { MethodInfo setMethod = property.GetSetMethod(/*nonPublic:*/ true); if (setMethod != null) { setMethod.Invoke(context, new object[] { value }); } } } /// /// Reads a value from the property that this MetaProperty represents, using the given /// object instance as the context. /// public object Read(object context) { if (_memberInfo is PropertyInfo) { return ((PropertyInfo)_memberInfo).GetValue(context, new object[] { }); } else { return ((FieldInfo)_memberInfo).GetValue(context); } } } }