当我尝试检索包含在动态加载的DLL中找到类型的实体列表的文档时,我得到 JSONSerialisation
异常,该异常表明它无法在动态加载的DLL中找到该类型: Could not load assembly 'Sandbox_One'
我使用RavenDB(build 2681)来存储使用Roslyn创建的实体,尽管我不认为这是一个问题 . 每个实体都继承一个非动态接口 IEntity
. Raven会话正在.NET MVC 4 Action的任一侧创建(根据Raven example),我能够将动态实体保存到 IEntity
列表中 .
当我尝试从文档中加载实体列表时,我收到序列化错误 . 目前,我只有一个实体类型(Customer)的单个实例(蓝眼睛) .
观察
- 在数据库中,实体看起来与我期望的完全一样:
{
"Entities": [
{
"$type": "Prometheus.Dynamic.Sandbox_One.Customer, Sandbox_One",
"Name": "Customer",
"Eye_colour": "Blue",
"Age": 9.0,
"Id": "b0937393-b1bf-4bcb-97d7-1aea7a96e881"
}
]
}
-
在加载实体时,我检查
AppDomain.CurrentDomain
表示已加载的程序集,Prometheus.Dynamic.Sandbox_One
表示Customer
类型 . -
Realm
对象有对动态加载的程序集的引用,我可以像这样反映它的类型:
var customer = Activator.CreateInstance(realm.Assembly.GetTypes().First());
- 在RavenDB会话启动后,程序集将加载到MVC操作中 . 这会有所作为吗?我想象的不是我期望JSON.net序列化程序在查看
AppDomain
.
代码和例外
异常的完整堆栈跟踪:
[JsonSerializationException: Could not load assembly 'Sandbox_One'.]
Raven.Imports.Newtonsoft.Json.Serialization.DefaultSerializationBinder.GetTypeFromTypeNameKey(TypeNameKey typeNameKey) in c:\Builds\RavenDB-Stable\Imports\Newtonsoft.Json\Src\Newtonsoft.Json\Serialization\DefaultSerializationBinder.cs:69
Raven.Imports.Newtonsoft.Json.Utilities.ThreadSafeStore`2.AddValue(TKey key) in c:\Builds\RavenDB-Stable\Imports\Newtonsoft.Json\Src\Newtonsoft.Json\Utilities\ThreadSafeStore.cs:62
Raven.Imports.Newtonsoft.Json.Serialization.DefaultSerializationBinder.BindToType(String assemblyName, String typeName) in c:\Builds\RavenDB-Stable\Imports\Newtonsoft.Json\Src\Newtonsoft.Json\Serialization\DefaultSerializationBinder.cs:119
Raven.Imports.Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ReadSpecialProperties(JsonReader reader, Type& objectType, JsonContract& contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue, Object& newValue, String& id) in c:\Builds\RavenDB-Stable\Imports\Newtonsoft.Json\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:473
[JsonSerializationException: Error resolving type specified in JSON 'Prometheus.Dynamic.Sandbox_One.Customer, Sandbox_One'. Path 'Entities[0].$type'.]
Raven.Imports.Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ReadSpecialProperties(JsonReader reader, Type& objectType, JsonContract& contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue, Object& newValue, String& id) in c:\Builds\RavenDB-Stable\Imports\Newtonsoft.Json\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:526
Raven.Imports.Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) in c:\Builds\RavenDB-Stable\Imports\Newtonsoft.Json\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:344
Raven.Imports.Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) in c:\Builds\RavenDB-Stable\Imports\Newtonsoft.Json\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:238
Raven.Imports.Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateList(IWrappedCollection wrappedList, JsonReader reader, JsonArrayContract contract, JsonProperty containerProperty, String id) in c:\Builds\RavenDB-Stable\Imports\Newtonsoft.Json\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:1132
Raven.Imports.Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateList(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue, String id) in c:\Builds\RavenDB-Stable\Imports\Newtonsoft.Json\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:572
Raven.Imports.Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) in c:\Builds\RavenDB-Stable\Imports\Newtonsoft.Json\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:240
Raven.Imports.Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target) in c:\Builds\RavenDB-Stable\Imports\Newtonsoft.Json\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:692
Raven.Imports.Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id) in c:\Builds\RavenDB-Stable\Imports\Newtonsoft.Json\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:1593
[JsonSerializationException: Could not read value for property: Entities]
Raven.Imports.Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id) in c:\Builds\RavenDB-Stable\Imports\Newtonsoft.Json\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:1602
Raven.Imports.Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) in c:\Builds\RavenDB-Stable\Imports\Newtonsoft.Json\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:368
Raven.Imports.Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) in c:\Builds\RavenDB-Stable\Imports\Newtonsoft.Json\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:238
Raven.Imports.Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent) in c:\Builds\RavenDB-Stable\Imports\Newtonsoft.Json\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:164
Raven.Imports.Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType) in c:\Builds\RavenDB-Stable\Imports\Newtonsoft.Json\Src\Newtonsoft.Json\JsonSerializer.cs:565
Raven.Client.Document.InMemoryDocumentSessionOperations.ConvertToEntity(Type entityType, String id, RavenJObject documentFound, RavenJObject metadata) in c:\Builds\RavenDB-Stable\Raven.Client.Lightweight\Document\InMemoryDocumentSessionOperations.cs:457
Raven.Client.Document.InMemoryDocumentSessionOperations.TrackEntity(Type entityType, String key, RavenJObject document, RavenJObject metadata, Boolean noTracking) in c:\Builds\RavenDB-Stable\Raven.Client.Lightweight\Document\InMemoryDocumentSessionOperations.cs:404
Raven.Client.Document.InMemoryDocumentSessionOperations.TrackEntity(Type entityType, JsonDocument documentFound) in c:\Builds\RavenDB-Stable\Raven.Client.Lightweight\Document\InMemoryDocumentSessionOperations.cs:388
Raven.Client.Document.InMemoryDocumentSessionOperations.TrackEntity(JsonDocument documentFound) in c:\Builds\RavenDB-Stable\Raven.Client.Lightweight\Document\InMemoryDocumentSessionOperations.cs:343
Raven.Client.Document.SessionOperations.LoadOperation.Complete() in c:\Builds\RavenDB-Stable\Raven.Client.Lightweight\Document\SessionOperations\LoadOperation.cs:61
Raven.Client.Document.DocumentSession.Load(String id) in c:\Builds\RavenDB-Stable\Raven.Client.Lightweight\Document\DocumentSession.cs:230
Prometheus.Core.DomainServices.DataManager.GetDataForRealm(IDocumentSession session, Realm realm) in c:\TeamProjectsCloud\Prometheus\Prometheus.Core\DomainServices\DataManager.cs:48
Prometheus.Portal.Controllers.DataController.Index(String entityName) in c:\TeamProjectsCloud\Prometheus\Prometheus.Portal\Controllers\DataController.cs:23
lambda_method(Closure , ControllerBase , Object[] ) +192
System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters) +274
System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters) +39
System.Web.Mvc.Async.c__DisplayClass39.b__33() +120
System.Web.Mvc.Async.c__DisplayClass4f.b__49() +452
System.Web.Mvc.Async.c__DisplayClass37.b__36(IAsyncResult asyncResult) +15
System.Web.Mvc.Async.c__DisplayClass2a.b__20() +33
System.Web.Mvc.Async.c__DisplayClass25.b__22(IAsyncResult asyncResult) +240
System.Web.Mvc.c__DisplayClass1d.b__18(IAsyncResult asyncResult) +28
System.Web.Mvc.Async.c__DisplayClass4.b__3(IAsyncResult ar) +15
System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +53
System.Web.Mvc.Async.c__DisplayClass4.b__3(IAsyncResult ar) +15
System.Web.Mvc.c__DisplayClass8.b__3(IAsyncResult asyncResult) +42
System.Web.Mvc.Async.c__DisplayClass4.b__3(IAsyncResult ar) +15
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +606
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +288
控制器(我已加粗实体加载的调用):NB RavenSession
继承自基本控制器,与MVC site example完全相同
public ActionResult Index(string entityName)
{
var viewModel = new DataViewModel();
var realm = realmManager.GetRealm(RavenSession, viewModel.SelectedRealm);
viewModel.Entities = realmManager.GetEntities(realm);
viewModel.CurrentEntity = viewModel.Entities.SingleOrDefault(x => x.Name == entityName);
viewModel.Data = dataManager.GetDataForRealm(RavenSession, realm); // Call to loading method
return View(viewModel);
}
抛出异常的Load调用:
public List<IEntity> GetDataForRealm(IDocumentSession session, Realm realm)
{
var realmData = session.Load<RealmData>(realm.RealmDataId); // Exception thrown
return realmData.Entities;
}
领域数据类:
public class RealmData
{
public RealmData()
{
Entities = new List<IEntity>();
}
public List<IEntity> Entities { get; set; }
}
预先感谢您的帮助!
1 回答
我的解决方案是在App Domain上实现
AssemblyResolve
事件处理程序 .GetDataForRealm
方法变为:事件处理程序如下所示:
What I believe was happening:
当JSON.Net反序列化器反映出动态类型时,它无法在
AppDomain.CurrentDomain
中找到程序集 . 当AppDomain
无法按名称查找程序集时,将调用该处理程序 . 我的程序集在AppDomain中(因为我使用了Assembly.Load)但是找不到它 .Note: 我用额外的参数扩展了
MyResolveEventHandler
,因为我已经有了我需要的程序集 . 如果你没有内存中的程序集(但知道它在哪里),那么你可以在MyResovleEventHandler
中加载它 .更新
您可能会发现以后在将这些结果对象分配给这些结果对象时遇到问题 . 这是因为通过
AppDomain
传递实体并不意味着它会更改对象的域 . 相反,它只是提交参考 . 相反,我发现使用在成员中具有动态程序集的自定义JSON转换器,首先让RavenDB更容易在正确的(临时)域中创建对象 . See that solution here .