自动映射器无法将Castle活动记录代理映射到多个目标类型

本文关键字:映射 代理 目标 类型 记录 Castle 活动 | 更新日期: 2023-09-27 18:12:40

这个问题似乎与我之前的问题有关。

我现在已经完成了在我的整个应用程序中实现AutoMapper,我只剩下一个在非常特殊的情况下不能工作的映射。

我已经把一个单元测试与一些假类,每次能够重现的问题,单元测试本身有一些设置配置ActiveRecord运行对内存数据库,我没有包括在这里(让我知道如果它可能是相关的)。

下面是单元测试:

[Test]
public void SandBox()
{
    Mapper.CreateMap<TestDbParty, TestCustomer>();
    Mapper.CreateMap<TestDbParty, TestLazyCustomer>();
    string customerId;
    using (Transaction.CreateParticipant())
    {
        var dbCustomer = new TestDbParty();
        dbCustomer.Save();
        customerId = dbCustomer.Id;
    }
    using (var uow = Transaction.CreateParticipant())
    {
        var dbCustomer = TestDbParty.Find(customerId);
        var customer = Mapper.Map<TestCustomer>(dbCustomer);
        var lazyCustomer = Mapper.Map<TestLazyCustomer>(dbCustomer);
    }
}
//Fake classes for unit test
public class TestCustomer 
{}
public class TestLazyCustomer : TestCustomer
{}
[ActiveRecord("PARTY", Lazy = true)]
public class TestDbParty : DbActiveRecord<TestDbParty>
{
    [PrimaryKey(PrimaryKeyType.Sequence, "ID", SequenceName = "PARTY_ID_SQ")]
    public virtual string Id { get; set; }
}

事务。CreateParticipant是一个用于设置SessionScope的包装器,下面是实现:

return new ActiveRecordTransactionParticipant((TransactionScope)SessionScope.Current 
?? new TransactionScope())

测试的最后一行将抛出以下异常:

System.InvalidCastException : Unable to cast object of type 'MyProject.TestCustomer' 
to type 'MyProject.TestLazyCustomer'.

现在,如果将测试更改为仅映射到LazyCustomer,它将按预期工作,或者如果将映射调用移到它们都工作的第一个事务中,则重新排序这两行,以便首先映射到lazy customer也可以工作。

我的猜测是城堡代理在某种程度上导致了这一点,但我不知道如何或如何才能可靠地解决这个问题。

编辑:我在失败行上设置了一个断点,并在立即窗口中运行dbCustomer.GetType(),这返回了Castle.Proxies.TestDbPartyProxy,因此似乎至少部分地证实了我的怀疑,当它们处于同一事务中时,映射将正常工作,因为对象实际上是TestDbParty的实例,而不是代理。

这绝对是问题所在,在移除TestDbParty类上的Lazy=true后,测试工作正常。

自动映射器无法将Castle活动记录代理映射到多个目标类型

这原来是Auto Mapper中的一个bug,复制的确切标准如下:

映射需要与运行时对象派生的源类型进行映射,在本例中是运行时使用的Active Record Proxy类型。

至少需要两个可能的目标类型,其中一个应该继承另一个。

最后,这个问题只会发生在先映射到基目标类,然后再映射到派生目标时,这是因为使用了映射缓存机制。

已经创建了git hub问题。

我不知道这个问题有什么可能的解决办法。