Permalink
Browse files

- first attempt at implementing sort of "installers" (as in WindsorIn…

…stallers) for mapping.

The extension point for that is called IMappingCatalog (for now) and is very barebone but it's a start.
  • Loading branch information...
1 parent 9d8be36 commit a5b162181728308c573b9b9af7f2d6a07e95d576 @kkozmic committed May 21, 2012
@@ -75,6 +75,7 @@
<Compile Include="ConversionPatterns\ToStringConversionPattern.cs" />
<Compile Include="ConversionPatternGenericCloserNonClosingTests.cs" />
<Compile Include="CustomConstructorTests.cs" />
+ <Compile Include="Internal\DelegatingCatalog.cs" />
<Compile Include="Internal\StringAssertEqualReporter.cs" />
<Compile Include="MappingDescriptorTests.cs" />
<Compile Include="MappingPatterns\MatchByPatternConversionPattern.cs" />
@@ -111,6 +112,7 @@
<Compile Include="Types\User2Dto.cs" />
<Compile Include="Types\UserDto.cs" />
<Compile Include="Types\ZipCode.cs" />
+ <Compile Include="UsingCatalogsTests.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Cartographer\Cartographer.csproj">
@@ -0,0 +1,22 @@
+namespace CartographerTests.Internal
+{
+ using System;
+ using Cartographer;
+ using Cartographer.Compiler;
+
+ //internal so that it doesn't get selected automatically
+ class DelegatingCatalog: IMappingCatalog
+ {
+ readonly Action<IIMappingBag> collect;
+
+ public DelegatingCatalog(Action<IIMappingBag> collect)
+ {
+ this.collect = collect;
+ }
+
+ public void Collect(IIMappingBag mappings)
+ {
+ collect(mappings);
+ }
+ }
+}
@@ -0,0 +1,21 @@
+namespace CartographerTests
+{
+ using Cartographer;
+ using Cartographer.Compiler;
+ using CartographerTests.Internal;
+ using CartographerTests.Types;
+ using Xunit;
+
+ public class UsingCatalogsTests
+ {
+ [Fact]
+ public void Can_register_mappings_via_catalog()
+ {
+ var builder = new MapperBuilder();
+ builder.AddCatalogs(new DelegatingCatalog(b => b.Add(new MappingInfo(typeof (Account), typeof (AccountDto), null))));
+ var mapper = builder.BuildMapper();
+
+ mapper.Convert<AccountDto>(new Account { Number = "number", Owner = new Person { Id = 3 } });
+ }
+ }
+}
@@ -53,13 +53,17 @@
<Compile Include="Compiler\IMappingStrategyBuilder.cs" />
<Compile Include="Compiler\IRootConversionPattern.cs" />
<Compile Include="Compiler\ITypeMatcher.cs" />
+ <Compile Include="Compiler\IIMappingBag.cs" />
+ <Compile Include="Compiler\MappingBag.cs" />
<Compile Include="Compiler\MappingCompiler.cs" />
<Compile Include="Compiler\MappingDescriptor.cs" />
<Compile Include="Compiler\MappingInfo.cs" />
<Compile Include="Compiler\MappingStrategy.cs" />
<Compile Include="Compiler\MappingStrategyBuilder.cs" />
<Compile Include="Helpers\CollectionConversionHelper.cs" />
+ <Compile Include="IMappingCatalog.cs" />
<Compile Include="Internal\Arguments.cs" />
+ <Compile Include="Internal\AssemblyExtensions.cs" />
<Compile Include="Internal\CollectionExtensions.cs" />
<Compile Include="Internal\Expressions\ExpressionType.cs" />
<Compile Include="Internal\Expressions\IReducingExpressionVisitor.cs" />
@@ -0,0 +1,7 @@
+namespace Cartographer.Compiler
+{
+ public interface IIMappingBag
+ {
+ IIMappingBag Add(MappingInfo mappingInfo);
+ }
+}
@@ -0,0 +1,20 @@
+namespace Cartographer.Compiler
+{
+ using System.Collections.Generic;
+
+ public class MappingBag: IIMappingBag
+ {
+ readonly ICollection<MappingInfo> mappings;
+
+ public MappingBag(ICollection<MappingInfo> mappings)
+ {
+ this.mappings = mappings;
+ }
+
+ public IIMappingBag Add(MappingInfo mappingInfo)
+ {
+ mappings.Add(mappingInfo);
+ return this;
+ }
+ }
+}
@@ -0,0 +1,9 @@
+namespace Cartographer
+{
+ using Cartographer.Compiler;
+
+ public interface IMappingCatalog
+ {
+ void Collect(IIMappingBag mappings);
+ }
+}
@@ -0,0 +1,20 @@
+namespace Cartographer.Internal
+{
+ using System;
+ using System.Reflection;
+
+ public static class AssemblyExtensions
+ {
+ public static Type[] GetAvailableTypes(this Assembly assembly)
+ {
+ try
+ {
+ return assembly.GetExportedTypes();
+ }
+ catch (ReflectionTypeLoadException e)
+ {
+ return Array.FindAll(e.Types, t => t != null);
+ }
+ }
+ }
+}
View
@@ -28,14 +28,6 @@ public Mapper(IMappingStrategyBuilder mappingStrategyBuilder, IMappingCompiler m
this.mappingCompiler = mappingCompiler;
}
- // TODO: this method temporarily serves as entry point to allow to pre-create mappings.
- // in a longer run this will be abstracted to something like IMappingCache or similar
- public void CreateMapping(Type sourceType, Type targetConstrtaintType, Type actualTargetType)
- {
- var key = Match(sourceType, targetConstrtaintType, actualTargetType);
- mappins.GetOrAdd(key, CreateMapping);
- }
-
public TTarget Convert<TTarget>(object source)
{
return ConvertWithArguments<TTarget>(source, null);
@@ -72,6 +64,13 @@ public TTarget ConvertWithArguments<TTarget>(object source, TTarget target, obje
});
}
+ internal void RegisterMapping(MappingInfo mappingInfo)
+ {
+ // this is temporary (famous last words)
+ var key = Match(mappingInfo);
+ mappins.GetOrAdd(key, CreateMapping);
+ }
+
Delegate CreateMapping(MappingInfo mappingInfo)
{
var strategy = mappingStrategyBuilder.BuildMappingStrategy(mappingInfo);
@@ -81,6 +80,11 @@ Delegate CreateMapping(MappingInfo mappingInfo)
MappingInfo Match(Type actualSourceType, Type targetConstrtaintType, Type actualTargetType)
{
var cacheKey = new MappingInfo(actualSourceType, targetConstrtaintType, actualTargetType);
+ return Match(cacheKey);
+ }
+
+ MappingInfo Match(MappingInfo cacheKey)
+ {
foreach (var matcher in typeMatchers)
{
if (matcher.Match(cacheKey))
@@ -3,13 +3,16 @@
using System;
using System.Collections.Generic;
using System.IO;
+ using System.Linq;
using System.Reflection;
using Cartographer.Compiler;
using Cartographer.Internal;
using Cartographer.Patterns;
public class MapperBuilder
{
+ readonly List<IMappingCatalog> catalogs = new List<IMappingCatalog>();
+
IMapper mapper;
public MapperBuilder()
@@ -19,6 +22,20 @@ public MapperBuilder()
public MapperBuilderSettings Settings { get; set; }
+ public MapperBuilder AddCatalogs(params IMappingCatalog[] catalogs)
+ {
+ this.catalogs.AddRange(catalogs);
+ return this;
+ }
+
+ public MapperBuilder AddCatalogsFromAssembly(Assembly assembly)
+ {
+ var types = assembly.GetAvailableTypes()
+ .Where(t => t.IsClass && t.IsAbstract == false && typeof (IMappingCatalog).IsAssignableFrom(t));
+ var mappingCatalogs = types.Select(t => Activator.CreateInstance(t) as IMappingCatalog).ToArray();
+ return AddCatalogs(mappingCatalogs);
+ }
+
public virtual IMapper BuildMapper()
{
if (mapper != null)
@@ -28,8 +45,19 @@ public virtual IMapper BuildMapper()
}
else
{
- mapper = new Mapper(Settings.MappingStrategyBuilder = Settings.MappingStrategyBuilder ?? BuildMappingStrategyBuilder(),
- Settings.MappingCompiler = Settings.MappingCompiler ?? BuildMappingCompiler(), Settings.TypeMatchers = Settings.TypeMatchers ?? BuildTypeMatchers());
+ var mapperLocal = new Mapper(Settings.MappingStrategyBuilder = Settings.MappingStrategyBuilder ?? BuildMappingStrategyBuilder(),
+ Settings.MappingCompiler = Settings.MappingCompiler ?? BuildMappingCompiler(), Settings.TypeMatchers = Settings.TypeMatchers ?? BuildTypeMatchers());
+ var mappings = new List<MappingInfo>();
+ var bag = new MappingBag(mappings);
+ foreach (var catalog in catalogs)
+ {
+ catalog.Collect(bag);
+ }
+ foreach (var mapping in mappings)
+ {
+ mapperLocal.RegisterMapping(mapping);
+ }
+ mapper = mapperLocal;
}
return mapper;
}

0 comments on commit a5b1621

Please sign in to comment.