// creates a serializer based on static registration (e.g. attributes), // generic templates or hardcoded mappings private ISerializer <T> CreateSerializer <T>() { var type = typeof(T); if (this.serializers.TryGetValue(type, out Type serializerType)) { return((ISerializer <T>)Activator.CreateInstance(serializerType)); } // is this type known as not serializable? if (!IsSerializable(type)) { return(new NonSerializer <T>()); } // is there a template for it? if (type.IsConstructedGenericType) { // generic // T is an instance of a generic type, such as Nullable<int> // and a corresponding generic serializer (template) is registered for the generic type var typeParams = type.GetGenericArguments(); var genericType = type.GetGenericTypeDefinition(); if (this.templates.TryGetValue(genericType, out serializerType)) { // we found a registered generic serializer, specialize it serializerType = serializerType.MakeGenericType(typeParams); return((ISerializer <T>)Activator.CreateInstance(serializerType, nonPublic: true)); } } // is the target type annotated with the [Serializer(typeof(MySerializer))] attribute var attribute = type.GetCustomAttribute <SerializerAttribute>(inherit: true /*!!!*/); if (attribute != null) { // if the annotation is on a generic type, the serializer is also generic and we need to instantiate the concrete serializer given the generic arguments if (type.IsConstructedGenericType && attribute.SerializerType.IsGenericTypeDefinition) { var typeParams = type.GetGenericArguments(); serializerType = attribute.SerializerType.MakeGenericType(typeParams); } else { serializerType = attribute.SerializerType; } return((ISerializer <T>)Activator.CreateInstance(serializerType)); } // for arrays, create an array serializer of the right type, // which in turn will delegate element serialization to the correct registered serializer if (type.IsArray) { if (type.GetArrayRank() != 1) { throw new NotSupportedException("Multi-dimensional arrays are currently not supported. A workaround would be to convert to a one-dimensional array."); } // instantiate the correct array serializer based on the type of elements in the array var itemType = type.GetElementType(); Type arraySerializer = Generator.IsSimpleValueType(itemType) ? typeof(SimpleArraySerializer <>) : typeof(ArraySerializer <>); serializerType = arraySerializer.MakeGenericType(itemType); return((ISerializer <T>)Activator.CreateInstance(serializerType, nonPublic: true)); } return(this.CreateWellKnownSerializer <T>()); }