protected override void OnApply(object target, MappingContext context) { // ....................................... // Process inherited read commands only foreach (ReadCommand read in this.InheritedReads.Values) { if (this.ReadCommands.Contains(read)) { continue; } read.Read(context); } // ....................................... // Check condition - only external read commands are available here if (this.Condition != null) { var condition = (bool)this.Condition.GetOuput(context, inheritedOnly: true); if (!condition) { return; } } // ....................................... // Process inner read commands only foreach (ReadCommand read in this.ReadCommands) { read.Read(context); } // ....................................... // Apply mapping operation object nextTarget = target; // Check condition if (this.TargetMember != null) { PropertyInfo property = this.TargetMember is PropertyInfo ? (PropertyInfo)this.TargetMember : null; FieldInfo field = this.TargetMember is FieldInfo ? (FieldInfo)this.TargetMember : null; // ....................................... // Get the command output object output = null; if (this.Value != null) { try { output = this.Value.GetOutput(context); } catch (Exception ex) { if (this.IsRequired) { throw new MappingException(String.Format("Failed to get the output of the map command for {0}.{1}. See inner exception for details.", this.TargetType.Name, this.TargetMember.Name), ex); } else { Log.Write(String.Format("Failed to get the output of the map command for {0}.{1}.", this.TargetType.Name, this.TargetMember.Name), ex); return; } } } // ....................................... // Get final value object value = null; if (output != null && !this.ValueType.IsAssignableFrom(output.GetType())) { // Try a converter when incompatible types are detected TypeConverter converter = TypeDescriptor.GetConverter(this.ValueType); if (converter != null && converter.CanConvertFrom(output.GetType())) { try { value = converter.ConvertFrom(output); } catch (Exception ex) { throw new MappingException(String.Format("Error while converting, '{0}' to {1} for applying to {2}.{3}, using TypeConverter.", output, this.ValueType, this.TargetType.Name, this.TargetMember.Name), ex); } } else // no type converter available { // Make C# 4.0 do all the implicit/explicit conversion work at runtime // social.msdn.microsoft.com/Forums/en-US/csharplanguage/thread/fe14d396-bc35-4f98-851d-ce3c8663cd79/ MethodInfo dynamicCastMethod = CastGenericMethod.MakeGenericMethod(this.ValueType); try { value = dynamicCastMethod.Invoke(null, new object[] { output }); } catch (Exception ex) { throw new MappingException(String.Format("Error while converting, '{0}' to {1} for applying to {2}.{3}. using dynamic cast.", output, this.ValueType, this.TargetType.Name, this.TargetMember.Name), ex); } } } else { // Try to create a new if (output == null && this.Value == null) { // Try to create an instance of the value type, since nothing was specified try { output = Activator.CreateInstance(this.ValueType); } catch (Exception ex) { throw new MappingException(String.Format("Cannot create a new instance of {0} for applying to {2}.{3}. (Did you forget the 'Value' attribute?)", this.ValueType, this.TargetType.Name, this.TargetMember.Name), ex); } } // Types might be compatible, just try to assign it value = output; } // ....................................... // Check for indexers if (Object.Equals(this.Indexer, MapCommand.ListAddingMode)) { IList list; try { // Try to get the list list = property != null ? (IList)property.GetValue(target, null) : (IList)field.GetValue(target); } catch (InvalidCastException ex) { throw new MappingException(String.Format("{0}.{1} is not an IList and cannot be set with the \"[]\" notation.", this.TargetType.Name, this.TargetMember.Name), ex); } catch (Exception ex) { throw new MappingException(String.Format("Error while mapping to {0}.{1}. See inner exception for details.", this.TargetType.Name, this.TargetMember.Name), ex); } if (list == null) { // List is empty, create a new list Type listType = property != null ? property.PropertyType : field.FieldType; try { list = (IList)Activator.CreateInstance(listType); } catch (Exception ex) { throw new MappingException(String.Format("Cannot create a new list of type {0} for applying to {2}.{3}. To avoid this error, make sure the list is not null before applying the mapping.", listType, this.TargetType.Name, this.TargetMember.Name), ex); } } if (property != null) { property.SetValue(target, list, null); } else { field.SetValue(target, list); } // Add to end of list list.Add(value); } else if (this.IndexerType != null) { // Actual indexer object indexer = null; if (this.Indexer is EvalComponent) { indexer = ((EvalComponent)this.Indexer).GetOuput(context, inheritedOnly: true); } else { indexer = this.Indexer; } Type collectionType = property != null ? property.PropertyType : field.FieldType; object collection; // Try to get the object with the indexer collection = property != null? property.GetValue(target, null) : field.GetValue(target); if (collection == null) { try { collection = Activator.CreateInstance(collectionType); } catch (Exception ex) { throw new MappingException(String.Format("Cannot create a new object of type {0} for applying to {2}.{3}. To avoid this error, make sure the property is not null before applying the mapping.", collectionType, this.TargetType.Name, this.TargetMember.Name), ex); } if (property != null) { property.SetValue(target, collection, null); } else { field.SetValue(target, collection); } } PropertyInfo itemProp = collectionType.GetProperty("Item"); itemProp.SetValue(collection, value, new object[] { indexer }); } else { // ....................................... // Apply to target member try { if (property != null) { // Apply to the property property.SetValue(target, value, null); } else if (field != null) { // Apply to the field field.SetValue(target, value); } } catch (Exception ex) { throw new MappingException(String.Format("Failed to map '{0}' to {1}.{2}. See inner exception for details.", value, this.TargetType.Name, this.TargetMember.Name), ex); } } nextTarget = value; } // ....................................... // Trickle down base.OnApply(nextTarget, context); }
internal void Read(MappingContext context) { // Read from source if necessary object rawValue; if (!context.FieldValues.TryGetValue(this.Field, out rawValue)) { if (context.Root.OnFieldRequired == null) { throw new MappingException("MappingConfiguration.OnFieldRequired is not set - you must supply a function that will return the required field value."); } try { rawValue = context.Root.OnFieldRequired(this.Field); } catch (Exception ex) { if (this.IsRequired) { throw new MappingException(String.Format("Failed to read field '{0}'. See inner exception for details.", this.Field), ex); } else { Log.Write(ToString(), String.Format("Failed to read field '{0}'.", Field), ex); return; } } context.FieldValues.Add(this.Field, rawValue); } ReadResult result; if (!context.ReadResults.TryGetValue(this, out result)) { // Process regular expressions result = new ReadResult() { FieldValue = rawValue == null ? null : rawValue.ToString() }; bool add = true; if (_regex != null && rawValue != null) { Match m = _regex.Match(result.FieldValue); if (m.Success) { foreach (string fragment in this.RegexFragments) { Group g = m.Groups[fragment]; if (g.Success) { ((dynamic)result)[fragment] = g.Value; } } } else { add = false; } } if (add) { context.ReadResults.Add(this, result); } } }