IObjectMapper <TImplementation> GetDictionaryToObjectConverter(ReadWriteProperty <TImplementation> property, Type valueType)
        {
            var underlyingType = Nullable.GetUnderlyingType(valueType);

            if (underlyingType != null)
            {
                var converterType = typeof(NullableValueObjectMapper <,>).MakeGenericType(typeof(TImplementation), underlyingType);

                return((IObjectMapper <TImplementation>)Activator.CreateInstance(converterType, property));
            }

            if (valueType.GetTypeInfo().IsEnum)
            {
                return(new EnumObjectMapper <TImplementation>(property));
            }

            if (valueType.IsArray)
            {
                var elementType = valueType.GetElementType();
                if (ValueObject.IsValueObjectType(elementType))
                {
                    var valueConverterType = typeof(ValueArrayObjectMapper <,>).MakeGenericType(typeof(TImplementation), elementType);
                    return((IObjectMapper <TImplementation>)Activator.CreateInstance(valueConverterType, property));
                }

                var elementConverter = _cache.GetConverter(elementType);

                var converterType = typeof(ObjectArrayObjectMapper <,>).MakeGenericType(typeof(TImplementation), elementType);
                return((IObjectMapper <TImplementation>)Activator.CreateInstance(converterType, property, elementConverter));
            }

            if (ValueObject.IsValueObjectType(valueType))
            {
                return(new ValueObjectMapper <TImplementation>(property));
            }

            if (valueType.ClosesType(typeof(IEnumerable <>)))
            {
                if (valueType.ClosesType(typeof(IDictionary <,>)))
                {
                    Type[] genericArguments = valueType.GetClosingArguments(typeof(IDictionary <,>)).ToArray();

                    var keyType     = genericArguments[0];
                    var elementType = genericArguments[1];


                    if (ValueObject.IsValueObjectType(keyType))
                    {
                        if (ValueObject.IsValueObjectType(elementType))
                        {
                            var valueConverterType = typeof(ValueValueDictionaryObjectMapper <, ,>).MakeGenericType(typeof(TImplementation), keyType, elementType);
                            return((IObjectMapper <TImplementation>)Activator.CreateInstance(valueConverterType, property));
                        }
                        else
                        {
                            var elementConverter   = _cache.GetConverter(elementType);
                            var valueConverterType = typeof(ValueObjectDictionaryObjectMapper <, ,>).MakeGenericType(typeof(TImplementation), keyType, elementType);
                            return((IObjectMapper <TImplementation>)Activator.CreateInstance(valueConverterType, property, elementConverter));
                        }
                    }

                    throw new InvalidOperationException("A dictionary with a reference type key is not supported: " + property.Property.Name);
                }

                if (valueType.ClosesType(typeof(IList <>)) || valueType.ClosesType(typeof(IEnumerable <>)))
                {
                    Type[] genericArguments = valueType.GetClosingArguments(typeof(IEnumerable <>)).ToArray();
                    var    elementType      = genericArguments[0];

                    if (ValueObject.IsValueObjectType(elementType))
                    {
                        var valueConverterType = typeof(ValueListObjectMapper <,>).MakeGenericType(typeof(TImplementation), elementType);

                        return((IObjectMapper <TImplementation>)Activator.CreateInstance(valueConverterType, property));
                    }

                    var elementConverter = _cache.GetConverter(elementType);

                    var converterType = typeof(ObjectListObjectMapper <,>).MakeGenericType(typeof(TImplementation), elementType);

                    return((IObjectMapper <TImplementation>)Activator.CreateInstance(converterType, property, elementConverter));
                }
            }

            return(new ObjectObjectMapper <TImplementation>(property, _cache.GetConverter(valueType)));
        }
示例#2
0
        IDictionaryMapper <T> GetDictionaryMapper(ReadOnlyProperty <T> property, Type valueType)
        {
            Type underlyingType;

            if (valueType.IsNullable(out underlyingType))
            {
                var converterType = typeof(NullableValueDictionaryMapper <,>).MakeGenericType(typeof(T),
                                                                                              underlyingType);

                return((IDictionaryMapper <T>)Activator.CreateInstance(converterType, property));
            }

            if (valueType.GetTypeInfo().IsEnum)
            {
                return(new EnumDictionaryMapper <T>(property));
            }

            if (valueType.IsArray)
            {
                var elementType = valueType.GetElementType();
                if (ValueObject.IsValueObjectType(elementType))
                {
                    return(new ValueDictionaryMapper <T>(property));
                }

                var elementConverter = _cache.GetConverter(elementType);

                var converterType = typeof(ObjectArrayDictionaryMapper <,>).MakeGenericType(typeof(T), elementType);
                return((IDictionaryMapper <T>)Activator.CreateInstance(converterType, property, elementConverter));
            }

            if (ValueObject.IsValueObjectType(valueType))
            {
                return(new ValueDictionaryMapper <T>(property));
            }

            if (valueType.HasInterface(typeof(IEnumerable <>)))
            {
                var elementType = valueType.GetClosingArguments(typeof(IEnumerable <>)).Single();

                if (valueType.ClosesType(typeof(IDictionary <,>)))
                {
                    Type[] arguments = valueType.GetClosingArguments(typeof(IDictionary <,>)).ToArray();
                    var    keyType   = arguments[0];
                    if (ValueObject.IsValueObjectType(keyType))
                    {
                        elementType = arguments[1];
                        if (ValueObject.IsValueObjectType(elementType))
                        {
                            var converterType = typeof(ValueValueDictionaryDictionaryMapper <, ,>).MakeGenericType(typeof(T), keyType, elementType);
                            return((IDictionaryMapper <T>)Activator.CreateInstance(converterType, property));
                        }
                        else
                        {
                            var converterType    = typeof(ValueObjectDictionaryDictionaryMapper <, ,>).MakeGenericType(typeof(T), keyType, elementType);
                            var elementConverter = _cache.GetConverter(elementType);
                            return((IDictionaryMapper <T>)Activator.CreateInstance(converterType, property, elementConverter));
                        }
                    }

                    throw new InvalidOperationException("Unable to map a reference type key dictionary");
                }

                if (valueType.ClosesType(typeof(IList <>)) || valueType.ClosesType(typeof(IEnumerable <>)))
                {
                    var converterType    = typeof(ObjectListDictionaryMapper <,>).MakeGenericType(typeof(T), elementType);
                    var elementConverter = _cache.GetConverter(elementType);

                    return((IDictionaryMapper <T>)Activator.CreateInstance(converterType, property, elementConverter));
                }
            }

            return(new ObjectDictionaryMapper <T>(property, _cache.GetConverter(valueType)));
        }