Attribute Processors

I’ve been busy working on other projects, so I haven’t worked on the serializer for a while, but I recently got back into things. I’ve recently added a new feature called Attribute Processors that will be included in an upcoming release. System.Attribute in .NET is a great thing, it allows you to specify extra information about a class, property, field, parameter, etc. right in the code. JsonExSerializer has about 5 attributes that is uses, JsonExIgnore and JsonExProperty probably being the most used. Before, certain places in the code would specifically look for attributes and apply some logic to deal with them. Now I’ve abstracted that out so that instances of the MetaData class (TypeData, PropertyData, etc) get passed through a list of AttributeProcessors. Those attribute processors can then look for attributes decorating class members or the classes themselves and then modify properties of the MetaData instance.

How is this useful? It’s useful to me in that it makes it very easy to add new attributes, and the code is cleanly separated so there is less chance of breaking things. It’s useful to everyone else in that you can now add your own custom attributes OR make use of existing attributes that may already be decorating your code.

Here’s a good example. Just about every serialization framework out there has some way of excluding properties from being serialized. Me too. Mine is called JsonExIgnore. You may be switching from an existing framework, or using 2 frameworks simultaneously. The built-in XmlSerializer uses the XmlIgnore attribute. I’ve added an AttributeProcessor class for it which is not turned on by default, but is very easy to add in.

Serializer serializer = new Serializer(typeof(MyClass));

// let's just use the XmlIgnore attribute that we already
// decorated our classes with so we don't have to type anymore
serializer.TypeHandlerFactory.AttributeProcessors.Add(new XmlIgnoreAttributeProcessor());

Here is the code for the XmlIgnoreAttributeProcessor:

public class XmlIgnoreAttributeProcessor : AttributeProcessor {
    public override void Process(MetaDataBase metaData, ICustomAttributeProvider attributeProvider, SerializationContext SerializationContext)    
    {
        if (metaData is IPropertyData) 
        {
            IPropertyData property = (IPropertyData)metaData;
            if (attributeProvider.IsDefined(typeof(XmlIgnoreAttribute), false))
                property.Ignored = true;        
        }    
    }
}

TypeData, PropertyData, FieldData all extend from MetaDataBase. They represent Types, properties, and fields respectively. If you’re only interested in one type of metadata then you need to check the metaData property to see what it is. IPropertyData is an interface that both PropertyData and FieldData implement. ICustomAttributeProvider is a .NET class that Reflection classes such as Type, MemberInfo, etc implement so that you can read their attributes. You query for the attribute(s) that your processor knows how to handle and then react accordingly if you find any. And that’s it.

Release 3.0 of JsonExSerializer

Release 3.0 of the Serializer is now here. This release contains some key customization enhancements. You now have very fine grained control over the serialization/deserialization process. I’ll blog more about this in some later posts.

I also fixed some localization issues plaguing those users outside the U.S. Dates and numbers now use the InvariantCulture to ensure consistent serialization/deserialization regardless of locale. Thanks guys for pointing those out!

Enjoy!

Pre-Optimization

I’m sure you’ve heard the saying “Pre-optimization is the root of all evil”, or something similar. Well I have too, and I knew it before writing the serializer. But sometimes I can’t help myself, I just know that doing it one way is going to be faster that some other way, or so I thought. The TokenStream class splits up the input stream into tokens. When I built the class I decided to only read from the physical reader if necessary when a token was requested by the parser. I’d gotten used to seeing that the Parser and Token stream classes took up most of the time spent during Deserialization when running them under the profiler. I figured it was just I/O taking so long and that I couldn’t do anything about it. Well I finally decided to try something a little different, so I made a quick change to read all the tokens up front and store them. Wow! What a difference! That one little change made it about 4 times faster. It went from about an average of 20ms down to 5ms. That may be nitpicky since we’re down here in the low millisecond range, but those numbers put us a lot closer to the Binary and Xml Serializers which I usually compare against. So it just goes to show that you should always profile and measure your optimizations to see if you’re really improving anything.

Follow

Get every new post delivered to your Inbox.