/// <summary> /// Visit the given builder <c>T</c> and optionally mutate it using /// information contained within the given Type. /// </summary> /// <param name="builder"> /// The builder being visited. /// </param> /// <param name="type"> /// The Type used to enrich the builder. /// </param> public virtual void Visit(T builder, Type type) { Portable portable = Attribute.GetCustomAttribute(type, typeof(Portable)) as Portable; // fast escape switch if (portable == null) { return; } // get header level information bool autoIndex = m_autoIndex; builder.SetType(type); // BindingFlags for member access const BindingFlags bindings = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; // get property level information PropertyInfo[] props = type.GetProperties(bindings); IList <string> fieldsExcluded = new List <string>(props.Length); for (int i = 0; i < props.Length; ++i) { PropertyInfo prop = props[i]; PortableProperty attribute = Attribute.GetCustomAttribute(prop, typeof(PortableProperty)) as PortableProperty; if (attribute == null) { continue; } string propName = prop.Name; string mangled = NameManglers.PROPERTY_MANGLER.Mangle(propName); ICodec codec = Codecs.GetCodec(attribute.Codec); if (!autoIndex && attribute.Index < 0) { throw new ArgumentException("A POF Index must be specified for the property " + type.Name + "#" + propName + " by specifying " + "within the annotation or enabling auto indexing"); } builder.AddAttribute( builder.NewAttribute() .SetName(mangled) .SetCodec(codec) .SetInvocationStrategy(new IS.PropertyInvcationStrategy <TB>(prop)) .SetIndex(attribute.Index).Build()); // field level annotations take precedence over accessor annotations fieldsExcluded.Add(mangled); } // get field level information FieldInfo[] fields = type.GetFields(bindings); for (int i = 0; i < fields.Length; ++i) { FieldInfo field = fields[i]; PortableProperty attribute = Attribute.GetCustomAttribute(field, typeof(PortableProperty)) as PortableProperty; if (attribute == null) { continue; } string fieldName = field.Name; string mangled = NameManglers.FIELD_MANGLER.Mangle(fieldName); ICodec codec = Codecs.GetCodec(attribute.Codec); if (!autoIndex && attribute.Index < 0) { throw new ArgumentException("A POF Index must be specified for the property " + type.Name + "#" + fieldName + " by specifying " + "within the annotation or enabling auto indexing"); } builder.AddAttribute( builder.NewAttribute() .SetName(mangled) .SetCodec(codec) .SetInvocationStrategy(new IS.FieldInvcationStrategy <TB>(field)) .SetIndex(attribute.Index).Build()); // field level annotations take precedence over accessor annotations fieldsExcluded.Add(mangled); } // get method level information MethodInfo[] methods = type.GetMethods(bindings); for (int i = 0; i < methods.Length; ++i) { MethodInfo method = methods[i]; PortableProperty attribute = Attribute.GetCustomAttribute(method, typeof(PortableProperty)) as PortableProperty; if (attribute == null) { continue; } string methodName = method.Name; if (methodName.StartsWith("Get") || methodName.StartsWith("Set") || methodName.StartsWith("Is")) { string mangled = NameManglers.METHOD_MANGLER.Mangle(methodName); if (fieldsExcluded.Contains(mangled)) { continue; } ICodec codec = Codecs.GetCodec(attribute.Codec); if (!autoIndex && attribute.Index < 0) { throw new ArgumentException("A POF Index must be specified for the method " + type.Name + "#" + methodName + " by specifying " + "within the annotation or enabling auto indexing"); } builder.AddAttribute( builder.NewAttribute() .SetName(mangled) .SetCodec(codec) .SetInvocationStrategy(new IS.MethodInvocationStrategy <TB>(method)) .SetIndex(attribute.Index).Build()); // in the case where both accessors (getters and setters) are // annotated we only use the values in the first annotation we // come stumble across fieldsExcluded.Add(mangled); } } }