自动映射器无法将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
后,测试工作正常。
这原来是Auto Mapper中的一个bug,复制的确切标准如下:
映射需要与运行时对象派生的源类型进行映射,在本例中是运行时使用的Active Record Proxy类型。
至少需要两个可能的目标类型,其中一个应该继承另一个。
最后,这个问题只会发生在先映射到基目标类,然后再映射到派生目标时,这是因为使用了映射缓存机制。
已经创建了git hub问题。
我不知道这个问题有什么可能的解决办法。