AutoMapper类型转换器中的依赖性问题

时间:2011-11-15 16:33:16

标签: castle-windsor automapper

我在使用AutoMapper和Windsor时遇到了问题。我创建了一个依赖于另一个对象的自定义类型转换器,可以从容器中解析但是当我尝试在映射过程中使用转换器时,抛出AutoMapper.AutoMapperMappingException,声明我的类型转换器没有默认构造函数。

我在下面的概念证明代码中重新创建了这个问题:

using System;
using System.Reflection;
using AutoMapper;
using Castle.MicroKernel.Registration;
using Castle.MicroKernel.SubSystems.Configuration;
using Castle.Windsor;
using NUnit.Framework;

public class ObjectOne
{
    public string Name { get; set; }
    public string Description { get; set; }
}

public class ObjectTwo
{
    public string ObjName { get; set; }
    public string ObjDescr { get; set; }
}

public interface ILoggingService
{
    void Log(string message);
}

public class ConsoleLogger : ILoggingService
{
    public void Log(string message)
    {
        Console.WriteLine(message);
    }
}

public class MyObjectConvertor : ITypeConverter<ObjectOne, ObjectTwo>
{
    private readonly ILoggingService _loggingService;

    public MyObjectConvertor(ILoggingService loggingService)
    {
        if (loggingService == null) throw new ArgumentNullException("loggingService");
        _loggingService = loggingService;
    }

    public ObjectTwo Convert(ResolutionContext context)
    {
        _loggingService.Log(MethodBase.GetCurrentMethod().ToString());
        var source = (ObjectOne)context.SourceValue;
        return new ObjectTwo { ObjName = source.Name, ObjDescr = source.Description };
    }

    public void LogIt(string message)
    {
        _loggingService.Log(message);
    }
}

public class MappingContractsWindsorInstaller : IWindsorInstaller
{
    public void Install(IWindsorContainer container, IConfigurationStore store)
    {
        container.Register(
            Component.For<ILoggingService>().ImplementedBy<ConsoleLogger>(),
            Component.For<MyObjectConvertor>());
    }
}

[TestFixture]
public class MappingTester
{
    private IWindsorContainer container;

    [TestFixtureSetUp]
    public void SetupFixture()
    {
        container = new WindsorContainer();
        container.Install(new MappingContractsWindsorInstaller());
        Mapper.CreateMap<ObjectOne, ObjectTwo>().ConvertUsing<MyObjectConvertor>();
        Mapper.Configuration.ConstructServicesUsing(container.Resolve);
        Mapper.AssertConfigurationIsValid();
    }

    [Test]
    public void MyObjectConvertorReturnedWithLoggerInjectedOk()
    {   // Proof that the Convertor is returned from the 
        // container with the dependency fulfilled
        var conv = container.Resolve<MyObjectConvertor>();
        conv.LogIt("Hello World");
    }

    [Test]
    public void ObjectOneMapsToTwo()
    {
        var source = new ObjectOne()
                    {
                        Name = "Foo",
                        Description = "Bar"
                    };

        var result = Mapper.Map<ObjectOne, ObjectTwo>(source);
        Assert.That(result.ObjName == source.Name);
        Assert.That(result.ObjDescr == source.Description);
    }
}

运行测试时,在ObjectOneMapsToTwo()期间抛出以下异常:

    Test 'MappingTester.ObjectOneMapsToTwo' failed: AutoMapper.AutoMapperMappingException : Trying to map ObjectOne to ObjectTwo.
Using mapping configuration for ObjectOne to ObjectTwo
Exception of type 'AutoMapper.AutoMapperMappingException' was thrown.
  ----> System.ArgumentException : Type 'MyObjectConvertor' does not have a default constructor
    at AutoMapper.MappingEngine.AutoMapper.IMappingEngineRunner.Map(ResolutionContext context)
    at AutoMapper.MappingEngine.Map(Object source, Type sourceType, Type destinationType, Action`1 opts)
    at AutoMapper.MappingEngine.Map[TSource,TDestination](TSource source)
    at AutoMapper.Mapper.Map[TSource,TDestination](TSource source)
    Class1.cs(99,0): at MappingTester.ObjectOneMapsToTwo()
    --ArgumentException
    at System.Linq.Expressions.Expression.New(Type type)
    at AutoMapper.DelegateFactory.<>c__DisplayClass1.<CreateCtor>b__0(Type t)
    at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
    at AutoMapper.DelegateFactory.CreateCtor(Type type)
    at AutoMapper.Mappers.ObjectCreator.CreateObject(Type type)
    at AutoMapper.MappingExpression`2.<ConvertUsing>b__1a[TTypeConverter]()
    at AutoMapper.DeferredInstantiatedConverter`2.Convert(ResolutionContext context)
    at AutoMapper.MappingExpression`2.<>c__DisplayClass15.<ConvertUsing>b__14(ResolutionContext context)
    at AutoMapper.Mappers.TypeMapObjectMapperRegistry.CustomMapperStrategy.Map(ResolutionContext context, IMappingEngineRunner mapper)
    at AutoMapper.Mappers.TypeMapMapper.Map(ResolutionContext context, IMappingEngineRunner mapper)
    at AutoMapper.MappingEngine.AutoMapper.IMappingEngineRunner.Map(ResolutionContext context)

此项目引用以下内容:

<packages>
  <package id="NUnit" version="2.5.10.11092" />
  <package id="Castle.Core" version="2.5.2" />
  <package id="Castle.Windsor" version="2.5.3" />
  <package id="AutoMapper" version="2.0.0" />
</packages>

测试MyObjectConvertorReturnedWithLoggerInjectedOk()传递,证明从容器返回了typeconvertor,并且依赖关系传递了OK。但是当Automapper尝试使用转换器时,它会抛出异常。

对此有任何帮助将不胜感激。

提前致谢。

1 个答案:

答案 0 :(得分:0)

这实际上是AutoMapper中的一个错误,在2.0版本之后修复,将在即将发布的2.1版本中发布。您可以拉下夜莺以获得AutoMapper.org

的最新稳定下降