Example #1
0
        public static object Create(Type type, params object[] ctorParams)
        {
            if (TypeFinder.IsImplicitValueType(type))
            {
                throw new ArgumentException("Cannot create an instance of a Value Type, Primitive Type, or string");
            }

            if (type.IsInterface)
            {
                throw new TypeLoadException("Cannot create an instance of an interface: " + type.Name);
            }

            return(Activator.CreateInstance(type, ctorParams));
        }
Example #2
0
        public void Map(object source, object target, MappingExecutionScope scope)
        {
            var ci = new PropertyMapDefinition
            {
                Source =
                {
                    Type  = source.GetType(),
                    Value = source
                },
                Target =
                {
                    Type  = target.GetType(),
                    Value = target
                }
            };

            var sourceProps = source.GetProperties();
            var targetProps = target.GetProperties();

            //create MemberExpressionSignature for each property
            var targetPropDefs = targetProps.Cast <PropertyDescriptor>()
                                 .Select(x => new
            {
                expression = new MemberExpressionSignature(
                    x.PropertyType,
                    typeof(TTarget),
                    x.Name),
                property = x
            }).ToArray();

            //before we map the members by name, we need to ignore any members that have been referenced in the member expressions
            var filteredTargetProps = new PropertyDescriptorCollection(
                (from t in targetPropDefs
                 where !_mapper.MappingContext.MemberExpressions.Any(x => x.Equals(t.expression))
                 select t.property).ToArray());

            foreach (PropertyDescriptor s in sourceProps)
            {
                var t = filteredTargetProps.Find(s.Name, false);
                if (t == null)
                {
                    continue;
                }
                var reflectedProp = ci.Target.Type.GetProperty(t.Name);
                if (reflectedProp == null)
                {
                    continue;
                }
                if (!reflectedProp.CanWrite)
                {
                    continue;
                }

                ci.SourceProp.Name  = s.Name;
                ci.SourceProp.Value = s.GetValue(source);
                ci.SourceProp.Type  = s.PropertyType;
                ci.TargetProp.Name  = t.Name;
                ci.TargetProp.Type  = t.PropertyType;
                ci.TargetProp.Value = t.GetValue(target);

                //if people have overridden this injector, we'll need to check that this hasn't already been mapped
                if (IsAlreadyMapped(ci))
                {
                    continue;
                }

                //check that we can proceed with setting this value
                if (IsTypeMappable(s.PropertyType, t.PropertyType))
                {
                    //set the output value to the source
                    ci.TargetProp.Value = ci.SourceProp.Value;
                }
                else
                {
                    var hasConverted = false;
                    // If no explicit mapping exists, but a TypeConverter exists between the source & destination types, use that
                    if (TypeFinder.IsImplicitValueType(ci.TargetProp.Type) &&
                        !IsMapperRegistered(ci.SourceProp.Type, ci.TargetProp.Type))
                    {
                        var converter = TypeDescriptor.GetConverter(ci.SourceProp.Type);
                        if (converter != null && converter.CanConvertTo(ci.TargetProp.Type))
                        {
                            ci.TargetProp.Value = converter.ConvertTo(ci.SourceProp.Value, ci.TargetProp.Type);
                            hasConverted        = true;
                        }
                        else
                        {
                            converter = TypeDescriptor.GetConverter(ci.TargetProp.Type);
                            if (converter != null && converter.CanConvertFrom(ci.SourceProp.Type))
                            {
                                ci.TargetProp.Value = converter.ConvertFrom(ci.SourceProp.Value);
                                hasConverted        = true;
                            }
                        }
                    }

                    if (!hasConverted)
                    {
                        // If we can't simply map it by setting the value, then we'll send the operation back through the mapper
                        // Also, if it's not a reference type, we can't map it in place and have to set the value of the property to a new value
                        if (TypeFinder.IsImplicitValueType(ci.TargetProp.Type) || ci.TargetProp.Value == null)
                        {
                            //map to new
                            var val = MapToNew(ci.SourceProp.Value, ci.SourceProp.Type, ci.TargetProp.Type, scope);
                            ci.TargetProp.Value = val;
                        }
                        else
                        {
                            //map to existing
                            MapToExisting(ci.SourceProp.Value, ci.TargetProp.Value, ci.SourceProp.Type, ci.TargetProp.Type);
                        }
                    }
                }

                SetProperty(reflectedProp, target, ci.TargetProp.Value, scope);
                //tag this as already mapped
                AddMemberMapped(ci);
            }

            //now that we've mapped by name, lets map by rule
            foreach (var signature in _mapper.MappingContext.MemberExpressions)
            {
                //get the target property definition with the expression mapped
                var targetProp = targetPropDefs.Single(x => x.expression.Equals(signature));

                var reflectedProp = ci.Target.Type.GetProperty(targetProp.property.Name);
                if (reflectedProp == null)
                {
                    throw new MissingMemberException("Could not access property " + targetProp.property.Name + " on object Type " + targetProp.property.ComponentType.Name);
                }

                //fill in the TypeMapDefinition object
                ci.TargetProp.Name = targetProp.property.Name;
                ci.TargetProp.Type = targetProp.property.PropertyType;

                //now, try to map from a rule, if successful set the value... the MapFromRule will automatically add the Info to the already mapped list.
                object val;
                if (!IsAlreadyMapped(ci) && _mapper.MappingContext.MapFromRule(ci, targetProp.expression, out val))
                {
                    if (!reflectedProp.CanWrite)
                    {
                        throw new MemberAccessException("A member expression has been declared for a writeable mapping operation for property " + targetProp.property.Name + " on object Type " + targetProp.property.ComponentType.Name + " but this property is readonly and cannot be written to");
                    }
                    SetProperty(reflectedProp, target, val, scope);
                    //tag this as already mapped
                    AddMemberMapped(ci);
                }
            }
        }