/// <summary> /// Adds a map /// </summary> public void AddMap(ITypeMapper mapper, TypeMapperMetadata metadata) { if (!_mappers.TryAdd(new TypeMapDefinition(metadata.SourceType, metadata.DestinationType), new MapperDefinition(mapper, metadata))) { throw new InvalidOperationException("Cannot add more than one mapping for the types " + metadata.SourceType.Name + ", " + metadata.DestinationType.Name); } }
internal AttemptTuple <MapperDefinition> TryGetMapper(Type source, Type target, bool createIfNonExistant) { Func <AttemptTuple <MapperDefinition> > findTypeMapper = () => { //if we have a specified TypeMapper for <TSource,Target> MapperDefinition mapper; if (_mappers.TryGetValue(new TypeMapDefinition(source, target), out mapper)) { return(new AttemptTuple <MapperDefinition>(true, mapper)); } //now, check if we have the specified mapper using type inheritance var found = _mappers.Where(x => x.Value.Metadata.PermitTypeInheritance && x.Value.Metadata.SourceType.IsAssignableFrom(source) && x.Value.Metadata.DestinationType.IsAssignableFrom(target)).ToArray(); if (found.Any()) { return(new AttemptTuple <MapperDefinition>(true, found.Single().Value)); } return(AttemptTuple <MapperDefinition> .False); }; var result = findTypeMapper(); if (result.Success) { return(result); } //if we've got this far, then create a new default map and add it to our mappers if (createIfNonExistant) { //need to lock as there could be many threads trying to do the same thing with the same types using (new WriteLockDisposable(_locker)) { //we'll now actually need to re-check if it exists result = findTypeMapper(); if (result.Success) { return(result); } //if both Source and Target types are Enumerables return new EnumerableTypeMapper<TSource,TTarget>() if (source.IsEnumerable() && target.IsEnumerable()) { var mapper = (ITypeMapper) Activator.CreateInstance(typeof(EnumerableTypeMapper <,>).MakeGenericType(source, target) , this); //pass this factory into the constructor //create the map and store it against our list var meta = new TypeMapperMetadata(source, target, false); var mapperDef = new MapperDefinition(mapper, meta); return(new AttemptTuple <MapperDefinition>(true, _mappers.GetOrAdd(new TypeMapDefinition(source, target), mapperDef))); } else { //if not enumerable, just create a normal map var concreteTypeMapper = typeof(TypeMapper <,>).MakeGenericType(new[] { source, target }); var mapper = (ITypeMapper)Creator.Create(concreteTypeMapper, this); var defaultMeta = new TypeMapperMetadata(source, target, false); var defaultMapperDef = new MapperDefinition(mapper, defaultMeta); return(new AttemptTuple <MapperDefinition>(true, _mappers.GetOrAdd(new TypeMapDefinition(source, target), defaultMapperDef))); } } } return(AttemptTuple <MapperDefinition> .False); }