gpt4 book ai didi

c# - Raven DB JsonSerializationException 无法加载程序集

转载 作者:太空宇宙 更新时间:2023-11-03 10:57:37 24 4
gpt4 key购买 nike

当我尝试检索包含在动态加载的 DLL 中找到其类型的实体列表的文档时,我得到一个 JSONSerialisation 异常,表明它无法在动态加载的 DLL 中找到类型DLL:无法加载程序集“Sandbox_One”

我正在使用 RavenDB(内部版本 2681)存储使用 Roslyn 创建的实体,虽然我认为这不是问题。每个实体都继承了一个非动态接口(interface) IEntity。 Raven Session 是在 .NET MVC 4 Action 的任一侧创建的(根据 Raven example ),我能够将动态实体保存到 IEntity 列表中。

当我尝试从文档中加载实体列表时,出现序列化错误。目前,我只有一个实体类型(客户)的一个实例(蓝眼睛)。

观察

  • 在数据库中,实体看起来与我预期的完全一样:
{  "Entities": [    {      "$type": "Prometheus.Dynamic.Sandbox_One.Customer, Sandbox_One",      "Name": "Customer",      "Eye_colour": "Blue",      "Age": 9.0,      "Id": "b0937393-b1bf-4bcb-97d7-1aea7a96e881"    }  ]}
  • At the point of Loading the entity, I check the AppDomain.CurrentDomain for the loaded assemblies and Prometheus.Dynamic.Sandbox_One with the Customer type is there.

  • The Realm object has a reference to the dynamically loaded Assembly and I am able to reflect types from it like so:

    var customer = Activator.CreateInstance(realm.Assembly.GetTypes().First());

  • The Assembly is loaded inside the MVC action, after the RavenDB session was started. Would that make a difference? I imagine not as I expect the JSON.net serializer is looking in the AppDomain.


Code and Exception

Full stack trace of the Exception:

[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

The controller (I've bolded the call where the Entities are loaded):NB RavenSession is inherited from a base controller exactly as in the 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; }
}

预先感谢您的帮助!

最佳答案

我的解决方案是在 App Domain 上实现一个 AssemblyResolve 事件处理程序。

GetDataForRealm 方法变为:

public List<IEntity> GetDataForRealm(IDocumentSession session, Realm realm)
{
AppDomain.CurrentDomain.AssemblyResolve += (s, a) => MyResolveEventHandler(s, a, realm.Assembly);

var realmData = session.Load<RealmData>(realm.RealmDataId);
return realmData.Entities;
}

事件处理程序如下所示:

private Assembly MyResolveEventHandler(object sender, ResolveEventArgs args, Assembly assembly)
{
if (assembly.GetName().Name == args.Name)
{
return assembly;
}
return null;
}

我认为发生了什么:

当 JSON.Net 反序列化器反射(reflect)出动态类型时,它无法在 AppDomain.CurrentDomain 中找到程序集。当 AppDomain 无法按名称找到程序集时调用处理程序。我的程序集位于 AppDomain 中(因为我使用的是 Assembly.Load),但找不到它。

注意:我用一个额外的参数扩展了 MyResolveEventHandler,因为我已经有了我需要的程序集。如果内存中没有程序集(但知道它在哪里),则可以将其加载到 MyResovleEventHandler 中。

更新

稍后您可能会发现在将数据分配给这些结果对象时遇到问题。这是因为通过 AppDomain 传递实体并不意味着它改变了对象的域。相反,它只是提供了一个引用。相反,我发现首先使用在成员中具有动态程序集的自定义 JSON 转换器让 RavenDB 在正确的(临时)域中创建对象更容易。 See that solution here .

关于c# - Raven DB JsonSerializationException 无法加载程序集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18878603/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com