/// <summary> /// Add a mapping of a data type to a projection type /// </summary> /// <typeparam name="TSourceType"></typeparam> /// <typeparam name="TDestType"></typeparam> /// <param name="defaultIncludes"></param> /// <param name="config"></param> /// <returns></returns> public PopcornConfiguration Map <TSourceType, TDestType>( string defaultIncludes = null, Action <MappingDefinitionConfiguration <TSourceType, TDestType> > config = null) { var sourceType = typeof(TSourceType); var destType = typeof(TDestType); // Validate and construct the actual default includes from both attributes and those passed in at the time of the mapping var destTypeInfo = typeof(TDestType).GetTypeInfo(); var parsedDefaultIncludes = (defaultIncludes == null) ? new List <PropertyReference> { } : (List <PropertyReference>)PropertyReference.Parse(defaultIncludes); defaultIncludes = PropertyReference.CompareAndConstructDefaultIncludes(parsedDefaultIncludes, destTypeInfo); var mappingConfiguration = new MappingDefinitionConfiguration <TSourceType, TDestType> { }; // Assign the existing mapping to be configured should it already exist if (_expander.Mappings.ContainsKey(sourceType)) { // We will allow a client to reference the same mapping multiple times to add more translations etc, // but ONLY if the types remain consistent! if (_expander.Mappings[sourceType].DefaultDestinationType != destType) { throw new InvalidOperationException($"Expander was default-mapped multiple times for {sourceType}."); } // Assign the existing mapping information mappingConfiguration.InternalMappingDefinition = _expander.Mappings[sourceType]; mappingConfiguration.InternalProjectionDefinition = _expander.Mappings[sourceType].Destinations[destType]; } else { // Create the configuration starting with the 'default' mapping mappingConfiguration.InternalMappingDefinition = new MappingDefinition { DefaultDestinationType = destType, }; // And assign it a projecion definition mappingConfiguration.InternalProjectionDefinition = new ProjectionDefinition { DefaultIncludes = defaultIncludes, DestinationType = destType, }; mappingConfiguration.InternalMappingDefinition.Destinations.Add(destType, mappingConfiguration.InternalProjectionDefinition); _expander.Mappings.Add(typeof(TSourceType), mappingConfiguration.InternalMappingDefinition); } if (config != null) { config(mappingConfiguration); } return(this); }
/// <summary> /// Add a mapping of a data type to a projection type /// </summary> /// <typeparam name="TSourceType"></typeparam> /// <typeparam name="TDestType"></typeparam> /// <param name="defaultIncludes"></param> /// <param name="config"></param> /// <returns></returns> public PopcornConfiguration Map <TSourceType, TDestType>( string defaultIncludes = null, Action <MappingDefinitionConfiguration <TSourceType, TDestType> > config = null) { var sourceType = typeof(TSourceType); var destType = typeof(TDestType); // Validate and construct the actual default includes from both attributes and those passed in at the time of the mapping var destTypeInfo = typeof(TDestType).GetTypeInfo(); var parsedDefaultIncludes = (defaultIncludes == null) ? new List <PropertyReference> { } : (List <PropertyReference>)PropertyReference.Parse(defaultIncludes); defaultIncludes = CompareAndConstructDefaultIncludes(parsedDefaultIncludes, destTypeInfo); var definition = new MappingDefinitionConfiguration <TSourceType, TDestType> { InternalDefinition = new MappingDefinition { DestinationType = destType, DefaultIncludes = defaultIncludes } }; // We will allow a client to reference the same mapping multiple times to add more translations etc, // but ONLY if the types remain consistent! if (_expander.Mappings.ContainsKey(sourceType)) { if (_expander.Mappings[sourceType].DestinationType != destType) { throw new InvalidOperationException( $"Expander was mapped multiple times but types do not match." + " {sourceType} was previously mapped to {this.Mappings[sourceType].DestinationType} and attempted to remap to {destType}." + " Only one destination type can be specified."); } if (defaultIncludes != null) { _expander.Mappings[sourceType].DefaultIncludes = defaultIncludes; } definition = new MappingDefinitionConfiguration <TSourceType, TDestType> { InternalDefinition = _expander.Mappings[sourceType] }; } else { _expander.Mappings.Add(typeof(TSourceType), definition.InternalDefinition); } if (config != null) { config(definition); } return(this); }