예제 #1
0
        /// <summary>
        /// Constructs a new instance
        /// </summary>
        /// <param name="context"></param>
        /// <param name="cache"></param>
        /// <param name="type"></param>
        /// <param name="fieldNameConvention"></param>
        public TypeData(FudgeContext context, TypeDataCache cache, Type type, FudgeFieldNameConvention fieldNameConvention)
        {
            Type = type;
            DefaultConstructor = type.GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, Type.EmptyTypes, null);
            Constructors       = type.GetConstructors();
            CustomAttributes   = type.GetCustomAttributes(true);

            cache.RegisterTypeData(this);

            fieldNameConvention = OverrideFieldNameConvention(type, fieldNameConvention);

            var kind         = CalcKind(context, cache, type, fieldNameConvention, out subType, out subType2, out fieldType);
            var inlineAttrib = GetCustomAttribute <FudgeInlineAttribute>();

            if (inlineAttrib != null)
            {
                kind = inlineAttrib.Inline ? TypeKind.Inline : TypeKind.Reference;
            }
            Kind = kind;

            if (kind != TypeKind.FudgePrimitive)        // If it's primitive we won't need to look inside it to serialize it
            {
                ScanProperties(context, cache, fieldNameConvention);
                ScanFields(context, cache, fieldNameConvention);

                PublicMethods       = type.GetMethods(BindingFlags.Public | BindingFlags.Instance);
                AllInstanceMethods  = type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
                StaticPublicMethods = type.GetMethods(BindingFlags.Public | BindingFlags.Static);
            }
        }
예제 #2
0
        private void ScanFields(FudgeContext context, TypeDataCache cache, FudgeFieldNameConvention fieldNameConvention)
        {
            var fields = Type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
            var list   = from field in fields
                         where field.GetCustomAttributes(typeof(FudgeTransientAttribute), true).Length == 0
                         select new PropertyData(cache, fieldNameConvention, field);

            Fields = list.ToArray();
        }
예제 #3
0
        private void ScanProperties(FudgeContext context, TypeDataCache cache, FudgeFieldNameConvention fieldNameConvention)
        {
            var props = Type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
            var list  = from prop in props
                        where prop.GetIndexParameters().Length == 0 &&          // We don't want to deal with anything with indices - e.g. this[string]
                        prop.GetCustomAttributes(typeof(FudgeTransientAttribute), true).Length == 0
                        select new PropertyData(cache, fieldNameConvention, prop);

            Properties = list.ToArray();
        }
예제 #4
0
            public override IFudgeSerializationSurrogate GetSurrogate(Type type, FudgeFieldNameConvention fieldNameConvention)
            {
                var fudgeSerializationSurrogate = _memoizer.Get(type, fieldNameConvention);

                if (fudgeSerializationSurrogate == null)
                {
                    throw new ArgumentException("Found a null surrogate for this type", "type"); // May expose our bugs
                }
                return(fudgeSerializationSurrogate);
            }
        /// <summary>
        /// Creates a surrogate for a given type.
        /// </summary>
        /// <param name="type">Type for which to get surrogate.</param>
        /// <param name="fieldNameConvention">Convention for mapping .net property names to serialized field names.</param>
        /// <returns>Surrogate for the type.</returns>
        /// <exception cref="FudgeRuntimeException">Thrown if no surrogate can be automatically created.</exception>
        public virtual IFudgeSerializationSurrogate GetSurrogate(Type type, FudgeFieldNameConvention fieldNameConvention)
        {
            var typeData = typeDataCache.GetTypeData(type, fieldNameConvention);

            foreach (var selector in selectors)
            {
                IFudgeSerializationSurrogate surrogate = selector(context, typeData);
                if (surrogate != null)
                {
                    return(surrogate);
                }
            }

            throw new FudgeRuntimeException("Cannot automatically determine surrogate for type " + type.FullName);
        }
예제 #6
0
        /// <summary>
        /// Gets the type data for a given type, constructing if necessary.
        /// </summary>
        /// <param name="type">Type for which to get data.</param>
        /// <param name="fieldNameConvention">Convention for mapping .net property names to serialized field names.</param>
        /// <returns><see cref="TypeData"/> for the given type.</returns>
        public TypeData GetTypeData(Type type, FudgeFieldNameConvention fieldNameConvention)
        {
            if (type == null)
                throw new ArgumentNullException("type");

            TypeData result;
            lock (cache)
            {
                if (!cache.TryGetValue(type, out result))
                {
                    result = new TypeData(context, this, type, fieldNameConvention);
                    Debug.Assert(cache.ContainsKey(type));                // TypeData registers itself during construction
                }
            }
            return result;
        }
예제 #7
0
            private PropertyData(TypeDataCache typeCache, FudgeFieldNameConvention fieldNameConvention, MemberInfo info, Type memberType)
            {
                this.info           = info;
                this.name           = info.Name;
                this.typeData       = typeCache.GetTypeData(memberType, fieldNameConvention);
                this.serializedName = GetSerializedName(info, fieldNameConvention);

                var inlineAttrib = GetCustomAttribute <FudgeInlineAttribute>();

                if (inlineAttrib == null)
                {
                    this.kind = typeData.Kind;
                }
                else
                {
                    this.kind = inlineAttrib.Inline ? TypeKind.Inline : TypeKind.Reference;
                }
            }
예제 #8
0
        /// <summary>
        /// Gets the type data for a given type, constructing if necessary.
        /// </summary>
        /// <param name="type">Type for which to get data.</param>
        /// <param name="fieldNameConvention">Convention for mapping .net property names to serialized field names.</param>
        /// <returns><see cref="TypeData"/> for the given type.</returns>
        public TypeData GetTypeData(Type type, FudgeFieldNameConvention fieldNameConvention)
        {
            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            TypeData result;

            lock (cache)
            {
                if (!cache.TryGetValue(type, out result))
                {
                    result = new TypeData(context, this, type, fieldNameConvention);
                    Debug.Assert(cache.ContainsKey(type));                // TypeData registers itself during construction
                }
            }
            return(result);
        }
예제 #9
0
            private string GetSerializedName(MemberInfo info, FudgeFieldNameConvention fieldNameConvention)
            {
                string name = info.Name;

                var fieldNameAttrib = GetCustomAttribute <FudgeFieldNameAttribute>();

                if (fieldNameAttrib != null)
                {
                    name = fieldNameAttrib.Name;
                }
                var dataMemberAttrib = GetCustomAttribute <DataMemberAttribute>();

                if (dataMemberAttrib != null && dataMemberAttrib.Name != null)
                {
                    name = dataMemberAttrib.Name;
                }

                // Now apply the naming convention
                switch (fieldNameConvention)
                {
                case FudgeFieldNameConvention.Identity:
                    return(name);

                case FudgeFieldNameConvention.AllLowerCase:
                    return(name.ToLower());

                case FudgeFieldNameConvention.AllUpperCase:
                    return(name.ToUpper());

                case FudgeFieldNameConvention.CamelCase:
                    return(name.Substring(0, 1).ToLower() + name.Substring(1));

                case FudgeFieldNameConvention.PascalCase:
                    return(name.Substring(0, 1).ToUpper() + name.Substring(1));

                default:
                    throw new FudgeRuntimeException("Unknown FudgeFieldNameConvention: " + fieldNameConvention.ToString());
                }
            }
예제 #10
0
        private static FudgeFieldNameConvention OverrideFieldNameConvention(Type type, FudgeFieldNameConvention fieldNameConvention)
        {
            var attribs = type.GetCustomAttributes(typeof(FudgeFieldNameConventionAttribute), true);

            if (attribs.Length > 0)
            {
                fieldNameConvention = ((FudgeFieldNameConventionAttribute)attribs[0]).Convention;
            }
            return(fieldNameConvention);
        }
예제 #11
0
 private IFudgeSerializationSurrogate GetSurrogateImpl(Type type, FudgeFieldNameConvention fieldNameConvention)
 {
     return(base.GetSurrogate(type, fieldNameConvention));
 }
예제 #12
0
 /// <summary>
 /// Determines whether this kind of surrogate can handle a given type
 /// </summary>
 /// <param name="cache"><see cref="TypeDataCache"/> for type data.</param>
 /// <param name="fieldNameConvention">Convention to use for renaming fields.</param>
 /// <param name="type">Type to test.</param>
 /// <returns>True if this kind of surrogate can handle the type.</returns>
 public static bool CanHandle(TypeDataCache cache, FudgeFieldNameConvention fieldNameConvention, Type type)
 {
     return(CanHandle(cache.GetTypeData(type, fieldNameConvention)));
 }
예제 #13
0
        /// <summary>
        /// Creates a surrogate for a given type.
        /// </summary>
        /// <param name="type">Type for which to get surrogate.</param>
        /// <param name="fieldNameConvention">Convention for mapping .net property names to serialized field names.</param>
        /// <returns>Surrogate for the type.</returns>
        /// <exception cref="FudgeRuntimeException">Thrown if no surrogate can be automatically created.</exception>
        public IFudgeSerializationSurrogate GetSurrogate(Type type, FudgeFieldNameConvention fieldNameConvention)
        {
            var typeData = typeDataCache.GetTypeData(type, fieldNameConvention);

            foreach (var selector in selectors)
            {
                IFudgeSerializationSurrogate surrogate = selector(context, typeData);
                if (surrogate != null)
                    return surrogate;
            }

            throw new FudgeRuntimeException("Cannot automatically determine surrogate for type " + type.FullName);
        }
 /// <summary>
 /// Determines whether this kind of surrogate can handle a given type
 /// </summary>
 /// <param name="cache"><see cref="TypeDataCache"/> for type data.</param>
 /// <param name="fieldNameConvention">Convention to use for renaming fields.</param>
 /// <param name="type">Type to test.</param>
 /// <returns>True if this kind of surrogate can handle the type.</returns>
 public static bool CanHandle(TypeDataCache cache, FudgeFieldNameConvention fieldNameConvention, Type type)
 {
     return CanHandle(cache.GetTypeData(type, fieldNameConvention));
 }
예제 #15
0
        private static TypeKind CalcKind(FudgeContext context, TypeDataCache typeCache, Type type, FudgeFieldNameConvention fieldNameConvention, out TypeData subType, out TypeData subType2, out FudgeFieldType fieldType)
        {
            // REVIEW 2010-02-14 t0rx -- There seems to be some duplication here with the FudgeSurrogateSelector, should look at joining up
            subType   = null;
            subType2  = null;
            fieldType = context.TypeDictionary.GetByCSharpType(type);
            if (fieldType != null)
            {
                // Just a simple field
                return(TypeKind.FudgePrimitive);
            }

            // Check for arrays
            if (type.IsArray)
            {
                subType = typeCache.GetTypeData(type.GetElementType(), fieldNameConvention);
                return(TypeKind.Inline);
            }

            // Check for dictionaries
            Type keyType, valueType;

            if (DictionarySurrogate.IsDictionary(type, out keyType, out valueType))
            {
                subType  = typeCache.GetTypeData(keyType, fieldNameConvention);
                subType2 = typeCache.GetTypeData(valueType, fieldNameConvention);
                return(TypeKind.Inline);
            }

            // Check for lists
            Type elementType;

            if (ListSurrogate.IsList(type, out elementType))
            {
                subType = typeCache.GetTypeData(elementType, fieldNameConvention);
                return(TypeKind.Inline);
            }

            return(TypeKind.Reference);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="FudgeFieldNameConventionAttribute"/> class.
 /// </summary>
 /// <param name="convention">Field name to use for this property.</param>
 public FudgeFieldNameConventionAttribute(FudgeFieldNameConvention convention)
 {
     this.Convention = convention;
 }
예제 #17
0
 /// <summary>
 /// Contructs a new instance based on a field
 /// </summary>
 /// <param name="typeCache"></param>
 /// <param name="fieldNameConvention"></param>
 /// <param name="info"></param>
 public PropertyData(TypeDataCache typeCache, FudgeFieldNameConvention fieldNameConvention, FieldInfo info)
     : this(typeCache, fieldNameConvention, info, info.FieldType)
 {
     this.getter = ReflectionUtil.CreateGetterDelegate(info);
     this.setter = ReflectionUtil.CreateSetterDelegate(info);
 }
예제 #18
0
 /// <summary>
 /// Initializes a new instance of the <see cref="FudgeFieldNameConventionAttribute"/> class.
 /// </summary>
 /// <param name="convention">Field name to use for this property.</param>
 public FudgeFieldNameConventionAttribute(FudgeFieldNameConvention convention)
 {
     this.Convention = convention;
 }