2

動的にロードされた DLL で型が見つかったエンティティのリストを含むドキュメントを取得しようとすると、動的にロードされた DLL で型が見つからないというJSONSerialisation例外が発生します。Could not load assembly 'Sandbox_One'

Roslynを使用して作成されたエンティティを格納するために RavenDB (ビルド 2681) を使用していますが、ここでは問題ではないと思います。各エンティティは、非動的インターフェースを継承しますIEntity。Raven セッションは .NET MVC 4 アクションの両側に作成されており ( Raven の例に従って)、動的エンティティを のリストに保存できますIEntity

エンティティのリストをドキュメントから読み込もうとすると、シリアル化エラーが発生します。現時点では、1 つのエンティティ タイプ (Customer) の 1 つのインスタンス (Blue Eyes) しかありません。

観察

  • データベースでは、エンティティは私が期待したとおりに見えます。
{
  "実体": [
    {
      "$type": "Prometheus.Dynamic.Sandbox_One.Customer, Sandbox_One",
      "名前": "顧客",
      "Eye_colour": "青",
      「年齢」: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: アセンブリ '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 キー) 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 リーダー、Type& objectType、JsonContract& 契約、JsonProperty メンバー、JsonContainerContract コンテナー契約、JsonProperty コンテナーメンバー、ObjectValue existing、Object& newValue、String& id) c:\Builds\RavenDB-Stable \Imports\Newtonsoft.Json\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:473

[JsonSerializationException: JSON 'Prometheus.Dynamic.Sandbox_One.Customer, Sandbox_One' で指定された型の解決中にエラーが発生しました。パス 'Entities[0].$type'.]
   Raven.Imports.Newtonsoft.Json.Serialization.JsonSerializerInternalReader.ReadSpecialProperties(JsonReader リーダー、Type& objectType、JsonContract& 契約、JsonProperty メンバー、JsonContainerContract コンテナー契約、JsonProperty コンテナーメンバー、ObjectValue existing、Object& newValue、String& id) c:\Builds\RavenDB-Stable \Imports\Newtonsoft.Json\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:526
   Raven.Imports.Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader リーダー、Type objectType、JsonContract 契約、JsonProperty メンバー、JsonContainerContract コンテナー契約、JsonProperty コンテナーメンバー、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 リーダー、タイプ objectType、JsonContract 契約、JsonProperty メンバー、JsonContainerContract コンテナー契約、JsonProperty コンテナーメンバー、オブジェクトの既存の値) c:\Builds\RavenDB-Stable\Imports\Newtonsoft.Json \Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:238
   c:\Builds\RavenDB-Stable\Imports\Newtonsoft.Json\Src\Newtonsoft.Json の Raven.Imports.Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateList(IWrappedCollection ラップリスト、JsonReader リーダー、JsonArrayContract コントラクト、JsonProperty コンテナー プロパティ、文字列 ID) \Serialization\JsonSerializerInternalReader.cs:1132
   c:\Builds\RavenDB-Stable\Imports\Newtonsoft.Json\Src\ の Raven.Imports.Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateList (JsonReader リーダー、Type objectType、JsonContract コントラクト、JsonProperty メンバー、Object existingValue、String id) Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:572
   Raven.Imports.Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader リーダー、タイプ objectType、JsonContract 契約、JsonProperty メンバー、JsonContainerContract コンテナー契約、JsonProperty コンテナーメンバー、オブジェクトの既存の値) c:\Builds\RavenDB-Stable\Imports\Newtonsoft.Json \Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:240
   Raven.Imports.Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty プロパティ、JsonConverter propertyConverter、JsonContainerContract コンテナContract、JsonProperty コンテナProperty、JsonReader リーダー、オブジェクト ターゲット) in c:\Builds\RavenDB-Stable\Imports\Newtonsoft.Json\Src\ Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:692
   c:\Builds\RavenDB-Stable\Imports\Newtonsoft.Json\Src\Newtonsoft.Json の Raven.Imports.Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject (オブジェクト newObject、JsonReader リーダー、JsonObjectContract コントラクト、JsonProperty メンバー、文字列 ID) \Serialization\JsonSerializerInternalReader.cs:1593

[JsonSerializationException: プロパティの値を読み取れませんでした: エンティティ]
   c:\Builds\RavenDB-Stable\Imports\Newtonsoft.Json\Src\Newtonsoft.Json の Raven.Imports.Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject (オブジェクト newObject、JsonReader リーダー、JsonObjectContract コントラクト、JsonProperty メンバー、文字列 ID) \Serialization\JsonSerializerInternalReader.cs:1602
   Raven.Imports.Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader リーダー、Type objectType、JsonContract 契約、JsonProperty メンバー、JsonContainerContract コンテナー契約、JsonProperty コンテナーメンバー、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 リーダー、タイプ objectType、JsonContract 契約、JsonProperty メンバー、JsonContainerContract コンテナー契約、JsonProperty コンテナーメンバー、オブジェクトの既存の値) c:\Builds\RavenDB-Stable\Imports\Newtonsoft.Json \Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:238
   c:\Builds\RavenDB-Stable\Imports\Newtonsoft.Json\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs の Raven.Imports.Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader リーダー、タイプ objectType、ブール値 checkAdditionalContent) :164
   c:\Builds\RavenDB-Stable\Imports\Newtonsoft.Json\Src\Newtonsoft.Json\JsonSerializer.cs:565 の Raven.Imports.Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader リーダー、タイプ objectType)
   c:\Builds\RavenDB-Stable\Raven.Client.Lightweight\Document\InMemoryDocumentSessionOperations.cs:457 の Raven.Client.Document.InMemoryDocumentSessionOperations.ConvertToEntity(Type entityType、String id、RavenJObject documentFound、RavenJObject メタデータ)
   c:\Builds\RavenDB-Stable\Raven.Client.Lightweight\Document\InMemoryDocumentSessionOperations.cs:404 の Raven.Client.Document.InMemoryDocumentSessionOperations.TrackEntity (Type entityType、String キー、RavenJObject ドキュメント、RavenJObject メタデータ、ブール値の noTracking)
   c:\Builds\RavenDB-Stable\Raven.Client.Lightweight\Document\InMemoryDocumentSessionOperations.cs:388 の Raven.Client.Document.InMemoryDocumentSessionOperations.TrackEntity(Type entityType, JsonDocument documentFound)
   c:\Builds\RavenDB-Stable\Raven.Client.Lightweight\Document\InMemoryDocumentSessionOperations.cs:343 の Raven.Client.Document.InMemoryDocumentSessionOperations.TrackEntity (JsonDocument documentFound)
   Raven.Client.Document.SessionOperations.LoadOperation.Complete() in c:\Builds\RavenDB-Stable\Raven.Client.Lightweight\Document\SessionOperations\LoadOperation.cs:61
   c:\Builds\RavenDB-Stable\Raven.Client.Lightweight\Document\DocumentSession.cs:230 の Raven.Client.Document.DocumentSession.Load(文字列 ID)
   c:\TeamProjectsCloud\Prometheus\Prometheus.Core\DomainServices\DataManager.cs:48 の Prometheus.Core.DomainServices.DataManager.GetDataForRealm (IDocumentSession セッション、Realm レルム)
   c:\TeamProjectsCloud\Prometheus\Prometheus.Portal\Controllers\DataController.cs:23 の Prometheus.Portal.Controllers.DataController.Index(String entityName)
   lambda_method(Closure , ControllerBase , Object[] ) +192
   System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 パラメーター) +274
   System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext、ActionDescriptor actionDescriptor、IDictionary`2 パラメーター) +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 ステップ、ブール値 & 完了した同期) +288

コントローラー (エンティティが読み込まれる呼び出しを太字にしました): NBは、 MVC サイトの例RavenSessionとまったく同じように、ベース コントローラーから継承されます。

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; }
}

よろしくお願いします。

4

1 に答える 1

2

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 デシリアライザーが動的型を反映していたときに、AppDomain.CurrentDomain. ハンドラーはAppDomain、アセンブリが名前で見つからない場合に呼び出されます。アセンブリは (Assembly.Load を使用したため) AppDomain にありましたが、見つかりませんでした。

注:MyResolveEventHandler必要なアセンブリが既にあるため、追加のパラメーターで 拡張しました。Assembly がメモリにない場合 (ただし、その場所がわかっている場合) は、 内に読み込むことができますMyResovleEventHandler

アップデート

後でこれらの結果オブジェクトにデータを割り当てる際に問題が発生することがあります。これは、エンティティを に渡してAppDomainも、オブジェクトのドメインが変更されるわけではないためです。代わりに、参照を渡すだけです。代わりに、メンバーに動的アセンブリを持つカスタム JSON コンバーターを使用して、RavenDB で最初に正しい (一時的な) ドメインにオブジェクトを作成する方が簡単であることがわかりました。ここでその解決策を参照してください

于 2013-09-19T08:50:11.513 に答える