Exemplo n.º 1
0
        // 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>());
        }