コード例 #1
0
ファイル: ODataAutoMapper.cs プロジェクト: vishal-sharma/Beef
        /// <summary>
        /// Gets from cache (or creates and adds to cache) the <see cref="IODataMapper"/> (with option to merge alternate property configuration).
        /// </summary>
        private static IODataMapper GetOrCreateMapper(Type type, Dictionary <string, MemberInfo> altProps, string overrideEntityName)
        {
            if (_cache.TryGetValue(type, out IODataMapper map))
            {
                return(map);
            }

            lock (_lock)
            {
                if (_cache.TryGetValue(type, out map))
                {
                    return(map);
                }

                if (!type.IsClass)
                {
                    throw new MapperException($"Type '{type.Name}' must be a class for auto-mapping.");
                }

                var mea = type.GetCustomAttributes(typeof(MapperEntityAttribute), true).OfType <MapperEntityAttribute>().FirstOrDefault();
                map = (IODataMapper)Activator.CreateInstance(typeof(ODataMapper <>).MakeGenericType(type), (overrideEntityName ?? mea?.Name) ?? type.Name);
                var    pe            = Expression.Parameter(type, "x");
                string dname         = null;
                var    hasProperties = false;

                MapperPropertyAttribute mpa = null;

                foreach (var p in TypeReflector.GetProperties(type))
                {
                    // Do not auto-map where the Ignore attribute has been specified.
                    if (p.GetCustomAttributes(typeof(MapperIgnoreAttribute), true).OfType <MapperIgnoreAttribute>().FirstOrDefault() != null)
                    {
                        continue;
                    }

                    // Get property merge config.
                    if (altProps == null)
                    {
                        mpa   = p.GetCustomAttributes(typeof(MapperPropertyAttribute), true).OfType <MapperPropertyAttribute>().FirstOrDefault();
                        dname = mpa?.Name;
                    }
                    else
                    {
                        if (!altProps.TryGetValue(p.Name, out MemberInfo alt))
                        {
                            throw new InvalidOperationException($"Type '{type.Name}' Property '{p.Name}' does not have an alternative property configuration specified.");
                        }

                        // Do not auto-map where the Ignore attribute has been specified.
                        if (alt.GetCustomAttributes(typeof(MapperIgnoreAttribute), true).OfType <MapperIgnoreAttribute>().FirstOrDefault() != null)
                        {
                            continue;
                        }

                        mpa   = alt.GetCustomAttributes(typeof(MapperPropertyAttribute), true).OfType <MapperPropertyAttribute>().FirstOrDefault();
                        dname = mpa?.Name ?? alt.Name;
                    }

                    // Create the lambda expression for the property and add to the mapper.
                    hasProperties = true;

                    var lex  = Expression.Lambda(Expression.Property(pe, p.Name), pe);
                    var pmap = (IODataPropertyMapper)map.GetType()
                               .GetMethod("Property", BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)
                               .MakeGenericMethod(p.PropertyType)
                               .Invoke(map, new object[] { lex, dname, mpa == null ? OperationTypes.Any : mpa.OperationTypes });

                    if (mpa == null)
                    {
                        continue;
                    }

                    // Apply auto-map Property attribute IsUnique configuration.
                    if (mpa.IsUniqueKey)
                    {
                        pmap.SetUniqueKey(mpa.IsUniqueKeyAutoGeneratedOnCreate);
                    }

                    // Apply auto-map Property attribute ConverterType configuration.
                    if (mpa.ConverterType != null)
                    {
                        if (!typeof(IPropertyMapperConverter).IsAssignableFrom(mpa.ConverterType))
                        {
                            throw new MapperException($"Type '{type.Name}' Property '{p.Name}' has 'MapperPropertyAttribute' with ConverterType set to '{mpa.ConverterType.Name}' which does not implement 'IPropertyMapperConverter'.");
                        }

                        IPropertyMapperConverter pmc = null;
                        var pdef = mpa.ConverterType.GetProperty("Default", BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.Static);
                        if (pdef == null)
                        {
                            if (mpa.ConverterType.GetConstructor(Type.EmptyTypes) == null)
                            {
                                throw new MapperException($"Type '{type.Name}' Property '{p.Name}' has 'MapperPropertyAttribute' with ConverterType set to '{mpa.ConverterType.Name}' does not have a static 'Default' property or default constructor.");
                            }

                            pmc = (IPropertyMapperConverter)Activator.CreateInstance(mpa.ConverterType);
                        }
                        else
                        {
                            pmc = (IPropertyMapperConverter)pdef.GetValue(null);
                        }

                        pmap.SetConverter(pmc);
                        continue;
                    }

                    // Apply auto-map Property attribute MapperType configuration for complex types.
                    if (pmap.IsSrceComplexType)
                    {
                        IEntityMapperBase em = null;
                        if (mpa.MapperType == null)
                        {
                            em = GetMapper(pmap.SrceComplexTypeReflector.ItemType);
                        }
                        else
                        {
                            if (!typeof(IEntityMapperBase).IsAssignableFrom(mpa.MapperType))
                            {
                                throw new MapperException($"Type '{type.Name}' Property '{p.Name}' has 'MapperPropertyAttribute' with MapperType set to '{mpa.MapperType.Name}' which does not implement 'IEntityMapper'.");
                            }

                            var mdef = mpa.MapperType.GetProperty("Default", BindingFlags.FlattenHierarchy | BindingFlags.Public | BindingFlags.Static);
                            if (mdef == null)
                            {
                                if (mpa.ConverterType.GetConstructor(Type.EmptyTypes) == null)
                                {
                                    throw new MapperException($"Type '{type.Name}' Property '{p.Name}' has 'MapperPropertyAttribute' with MapperType set to '{mpa.MapperType.Name}' does not have a static 'Default' property or default constructor.");
                                }

                                em = (IEntityMapperBase)Activator.CreateInstance(mpa.MapperType);
                            }
                            else
                            {
                                em = (IEntityMapperBase)mdef.GetValue(null);
                            }
                        }

                        if (em != null)
                        {
                            pmap.SetMapper(em);
                        }
                    }
                    else if (mpa.MapperType != null)
                    {
                        throw new MapperException($"Type '{type.Name}' Property '{p.Name}' has 'MapperPropertyAttribute' with MapperType set to '{mpa.ConverterType.Name}' although the property is not a complex type.");
                    }
                }

                if (!hasProperties)
                {
                    throw new MapperException($"AutoMapper has found no properties for Type '{type.Name}' that it is able to auto-map.");
                }

                _cache.Add(type, map);
                return(map);
            }
        }
コード例 #2
0
 public static T MapTo <T>(this object from, params object[] ctorParameters)
     where T : class
 {
     if (from != null)
     {
         ConstructorInfo ctor = typeof(T).GetConstructor(ctorParameters.Select(p => p.GetType()).ToArray());
         if (ctor == null)
         {
             throw new ArgumentException("Invalid Constructor Parameters");
         }
         T result = (T)ctor.Invoke(ctorParameters);
         IEnumerable <PropertyInfo> properties = from.GetType().GetProperties()
                                                 .Where(p => p.CanRead && !p.IsDefined(typeof(MapperIgnoreAttribute)));
         foreach (PropertyInfo property in properties)
         {
             try
             {
                 MapperPropertyAttribute propAttribute = property.GetCustomAttribute <MapperPropertyAttribute>();
                 PropertyInfo            resultProp    = typeof(T).GetRuntimeProperty(
                     propAttribute?.PropertyName ?? property.Name
                     );
                 if (
                     resultProp != null &&
                     !resultProp.IsDefined(typeof(MapperIgnoreAttribute)) &&
                     resultProp.CanWrite
                     )
                 {
                     if (TypeDescriptor.GetConverter(property.PropertyType).CanConvertTo(resultProp.PropertyType))
                     {
                         resultProp.SetValue(result, Convert.ChangeType(property.GetValue(from), resultProp.PropertyType));
                     }
                     else if (property.PropertyType == typeof(string))
                     {
                         if (resultProp.PropertyType == typeof(int))
                         {
                             resultProp.SetValue(result, int.Parse(property.GetValue(from).ToString()));
                         }
                         else if (resultProp.PropertyType == typeof(DateTime))
                         {
                             resultProp.SetValue(result, DateTime.Parse(property.GetValue(from).ToString()));
                         }
                         else if (resultProp.PropertyType == typeof(bool))
                         {
                             resultProp.SetValue(result, bool.Parse(property.GetValue(from).ToString()));
                         }
                         else if (resultProp.PropertyType == typeof(double))
                         {
                             resultProp.SetValue(result, double.Parse(property.GetValue(from).ToString()));
                         }
                         else if (resultProp.PropertyType == typeof(float))
                         {
                             resultProp.SetValue(result, float.Parse(property.GetValue(from).ToString()));
                         }
                     }
                 }
             }
             catch (Exception) { }
         }
         return(result);
     }
     else
     {
         return(null);
     }
 }