Automapper 无法将 Castle Activerecord 代理映射到多个目标类型
Auto mapper is failing to map a Castle Active Record Proxy to multiple destination types
这个问题似乎与我的有关。
我现在已经在我的整个应用程序中完成了 AutoMapper 的实现,我只剩下一张地图在非常特殊的情况下不起作用。
我已经将单元测试与一些假 classes 放在一起,每次都能重现问题,单元测试本身有一些设置,可以将 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; }
}
Transaction.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,它会按预期工作,或者如果将映射调用移至第一个 t运行saction,它们都会工作,重新排序这两行,以便惰性先映射客户也可以。
我的猜测是 Castle 代理以某种方式导致了此问题,但我不知道如何或如何可靠地解决此问题。
编辑: 我在失败的行上放置了一个断点,运行 dbCustomer.GetType()
在立即的 window 中,这返回了 Castle.Proxies.TestDbPartyProxy
所以这似乎至少部分证实了我的怀疑,当它们在同一个 t运行saction 中时映射会工作正常,因为该对象实际上是 TestDbParty
的实例而不是代理。
这绝对是问题所在,删除 TestDbParty
class 上的 Lazy=true
后测试正常。
这原来是 Auto Mapper 中的一个错误,重现的确切标准如下:
映射需要与运行时对象派生自的源类型进行映射,在本例中是在运行时使用的 Active Record 代理类型。
至少需要有两种可能的目标类型,其中一种应继承另一种。
最后,只有当先映射到基本目的地 class,然后再映射到派生目的地时才会出现此问题,这是因为使用了地图缓存机制。
已为此创建 git hub issue。
我不知道这个问题有任何可能的解决方法。
这个问题似乎与我的
我现在已经在我的整个应用程序中完成了 AutoMapper 的实现,我只剩下一张地图在非常特殊的情况下不起作用。
我已经将单元测试与一些假 classes 放在一起,每次都能重现问题,单元测试本身有一些设置,可以将 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; }
}
Transaction.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,它会按预期工作,或者如果将映射调用移至第一个 t运行saction,它们都会工作,重新排序这两行,以便惰性先映射客户也可以。
我的猜测是 Castle 代理以某种方式导致了此问题,但我不知道如何或如何可靠地解决此问题。
编辑: 我在失败的行上放置了一个断点,运行 dbCustomer.GetType()
在立即的 window 中,这返回了 Castle.Proxies.TestDbPartyProxy
所以这似乎至少部分证实了我的怀疑,当它们在同一个 t运行saction 中时映射会工作正常,因为该对象实际上是 TestDbParty
的实例而不是代理。
这绝对是问题所在,删除 TestDbParty
class 上的 Lazy=true
后测试正常。
这原来是 Auto Mapper 中的一个错误,重现的确切标准如下:
映射需要与运行时对象派生自的源类型进行映射,在本例中是在运行时使用的 Active Record 代理类型。
至少需要有两种可能的目标类型,其中一种应继承另一种。
最后,只有当先映射到基本目的地 class,然后再映射到派生目的地时才会出现此问题,这是因为使用了地图缓存机制。
已为此创建 git hub issue。
我不知道这个问题有任何可能的解决方法。