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)); }
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); } } }