Exemple #1
0
        /// <summary>
        /// Inherits the properties from the selected <paramref name="inheritMapper"/>.
        /// </summary>
        /// <param name="inheritMapper">The <see cref="IDatabaseMapper"/> to inherit from.</param>
        public void InheritPropertiesFrom <T>(IDatabaseMapper <T> inheritMapper) where T : class, new()
        {
            if (inheritMapper == null)
            {
                throw new ArgumentNullException(nameof(inheritMapper));
            }

            if (!SrceType.GetTypeInfo().IsSubclassOf(typeof(T)))
            {
                throw new ArgumentException($"Type {typeof(T).Name} must inherit from {SrceType.Name}.");
            }

            var pe   = Expression.Parameter(SrceType, "x");
            var type = typeof(DatabaseMapper <>).MakeGenericType(SrceType);

            foreach (var p in inheritMapper.Mappings.OfType <IDatabasePropertyMapper>())
            {
                var lex  = Expression.Lambda(Expression.Property(pe, p.SrcePropertyName), pe);
                var pmap = (IDatabasePropertyMapper)type
                           .GetMethod("Property", BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)
                           .MakeGenericMethod(p.SrcePropertyType)
                           .Invoke(this, new object[] { lex, p.DestPropertyName, p.OperationTypes });

                if (p.IsUniqueKey)
                {
                    pmap.SetUniqueKey(p.IsUniqueKeyAutoGeneratedOnCreate);
                }

                pmap.DestDbType = p.DestDbType;
                pmap.SetConverter(p.Converter);
                pmap.SetMapper(p.Mapper);
            }
        }
Exemple #2
0
        /// <summary>
        /// Initialises a new instance of the <see cref="ODataMapper{TSrce}"/> class.
        /// </summary>
        /// <param name="odataEntityName">The <b>OData</b> entity name as represented within the URL.</param>
        public ODataMapper(string odataEntityName)
        {
            ODataEntityName = string.IsNullOrEmpty(odataEntityName) ? throw new ArgumentNullException(nameof(odataEntityName)) : odataEntityName;
            if (typeof(IETag).IsAssignableFrom(typeof(TSrce)))
            {
                Property(x => ((IETag)x).ETag, ODataETagPropertyName).MapSrceToDestWhen((v) => false);
            }

            _hasDefaultCtor = SrceType.GetConstructor(Type.EmptyTypes) != null;
            if (!_hasDefaultCtor)
            {
                // This is required to support the likes of compiler generated Types when using LINQ queries.
                _orderedProperties = SrceType.GetProperties(BindingFlags.Public | BindingFlags.Instance).Select(x => x.Name).ToArray();
                if (SrceType.GetConstructors().Where(x => x.GetParameters().Length == _orderedProperties.Length).Count() == 0)
                {
                    throw new MapperException($"Type {SrceType.Name} does not have default constructor, or a constructor that accepts all properties; unable to determine constructor.");
                }
            }
        }
Exemple #3
0
        /// <summary>
        /// Automatically map commonly named properties.
        /// </summary>
        private void AutomagicallyMap(string[] ignoreSrceProperties)
        {
            MapperPropertyAttribute mpa = null;

            foreach (var sp in SrceType.GetProperties(BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.SetProperty | BindingFlags.Instance))
            {
                // Do not auto-map where ignore has been specified.
                if (ignoreSrceProperties.Contains(sp.Name))
                {
                    continue;
                }

                if (sp.GetCustomAttributes(typeof(MapperIgnoreAttribute), true).OfType <MapperIgnoreAttribute>().FirstOrDefault() != null)
                {
                    continue;
                }

                // Find corresponding property.
                mpa = sp.GetCustomAttributes(typeof(MapperPropertyAttribute), true).OfType <MapperPropertyAttribute>().FirstOrDefault();
                var dname = mpa == null || string.IsNullOrEmpty(mpa.Name) ? sp.Name : mpa.Name;
                var dp    = DestType.GetProperty(dname, BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.SetProperty | BindingFlags.Instance);
                if (dp == null)
                {
                    if (mpa != null)
                    {
                        throw new InvalidOperationException($"Type '{SrceType.Name}' Property '{sp.Name}' has 'MapperPropertyAttribute' with Name set to '{dname}' which does not exist for destination Type '{DestType.Name}'.");
                    }

                    continue;
                }

                // Create the lambda expressions for the property and add to the mapper.
                var spe  = Expression.Parameter(SrceType, "x");
                var sex  = Expression.Lambda(Expression.Property(spe, sp.Name), spe);
                var dpe  = Expression.Parameter(DestType, "x");
                var dex  = Expression.Lambda(Expression.Property(dpe, dname), dpe);
                var pmap = (IPropertyMapper <TSrce, TDest>) typeof(EntityMapper <TSrce, TDest>)
                           .GetMethod("PropertySrceAndDest", BindingFlags.NonPublic | BindingFlags.Instance)
                           .MakeGenericMethod(new Type[] { sp.PropertyType, dp.PropertyType })
                           .Invoke(this, new object[] { sex, dex });

                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 '{SrceType.Name}' Property '{sp.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 '{SrceType.Name}' Property '{sp.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)
                    {
                        if (!typeof(IEntityMapperBase).IsAssignableFrom(mpa.MapperType))
                        {
                            throw new MapperException($"Type '{SrceType.Name}' Property '{sp.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 '{SrceType.Name}' Property '{sp.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 '{SrceType.Name}' Property '{sp.Name}' has 'MapperPropertyAttribute' with MapperType set to '{mpa.ConverterType.Name}' although the property is not a complex type.");
                }
            }
        }