Ошибка при десериализации файла в AutoCAD

Автор Тема: Ошибка при десериализации файла в AutoCAD  (Прочитано 8825 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн EvgivachevАвтор темы

  • ADN OPEN
  • Сообщений: 16
  • Карма: 0
Добрый день! Столкнулся с такой проблемой, что при запуске команды в AutoCAD, которая десериализует текстовый файл, выпадает ошибка
Цитировать
Не удалось загрузить тип System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[GraphAssembly.Node, GraphAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], необходимый для десериализации.
Странно, что код десериализации файла работает, если запустить его в новом, например, консольном проекте.
Подскажите, пожалуйста, с чем это может быть связано, как исправить?
Код - C# [Выбрать]
  1.  var res = new GraphAssembly.Graph();
  2.                             using (var s = File.Open(pathTofileGraph, FileMode.Open))
  3.                             {
  4.                                 var bFormatter = new BinaryFormatter();
  5.                                 bFormatter.AssemblyFormat =
  6.                                     System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;
  7.                                 bFormatter.Binder = new MyBinder(); // MyBinder class code given below
  8.                                 try
  9.                                 {
  10.                                     res = (Graph)bFormatter.Deserialize(s);
  11.                                     var print = res.Print();
  12.                                 }
  13.                                 catch (SerializationException se)
  14.                                 {
  15.                                     Debug.WriteLine(se.Message);
  16.                                 }
  17.                             }
Код - C# [Выбрать]
  1.  internal sealed class MyBinder : SerializationBinder
  2.     {
  3.         public override Type BindToType(string assemblyName, string typeName)
  4.         {
  5.             Type ttd = null;
  6.             try
  7.             {
  8.                 string toassname = assemblyName.Split(',')[0];
  9.                 Assembly[] asmblies = AppDomain.CurrentDomain.GetAssemblies();
  10.                 foreach (Assembly ass in asmblies)
  11.                 {
  12.                     if (ass.FullName.Split(',')[0] == toassname)
  13.                     {
  14.                         ttd = ass.GetType(typeName, false, true);
  15.                         if (ttd is null)
  16.                         {
  17.                             Debug.WriteLine($"Не найден тип \"{typeName}\" в сборке {toassname}");
  18.                         }
  19.                         else break;
  20.                     }
  21.                 }
  22.             }
  23.             catch (System.Exception e)
  24.             {
  25.                 Debug.WriteLine(e.Message);
  26.             }
  27.             return ttd;
  28.         }
  29.     }

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Evgivachev,
Начни с чтения правила о форматировании кода на нашем форуме и исправь код у себя в сообщении.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Код - C# [Выбрать]
  1. internal sealed class MyBinder : SerializationBinder
  2.     {
  3.         public override Type BindToType(string assemblyName, string typeName)
  4.         {
  5.             Type ttd = null;
  6.             try
  7.             {
  8.                 string toassname = assemblyName.Split(',')[0];
  9.                 Assembly[] asmblies = AppDomain.CurrentDomain.GetAssemblies();
  10.                 foreach (Assembly ass in asmblies)
  11.                 {
  12.                     if (ass.FullName.Split(',')[0] == toassname)
  13.                     {
  14.                         ttd = ass.GetType(typeName, false, true);
  15.                         if (ttd is null)
  16.                         {
  17.                             Debug.WriteLine($"Не найден тип \"{typeName}\" в сборке {toassname}");
  18.                         }
  19.                         else break;
  20.                     }
  21.                 }
  22.             }
  23.             catch (System.Exception e)
  24.             {
  25.                 Debug.WriteLine(e.Message);
  26.             }
  27.             return ttd;
  28.         }
  29.     }
Зачем это все? Почему просто не взять Assembly.GetExecutingAssembly()?

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Пример с MSDN
Код - C# [Выбрать]
  1. sealed class Version1ToVersion2DeserializationBinder : SerializationBinder
  2. {
  3.     public override Type BindToType(string assemblyName, string typeName)
  4.     {
  5.         Type typeToDeserialize = null;
  6.  
  7.         // For each assemblyName/typeName that you want to deserialize to
  8.         // a different type, set typeToDeserialize to the desired type.
  9.         String assemVer1 = Assembly.GetExecutingAssembly().FullName;
  10.         String typeVer1 = "Version1Type";
  11.  
  12.         if (assemblyName == assemVer1 && typeName == typeVer1)
  13.         {
  14.             // To use a type from a different assembly version,
  15.             // change the version number.
  16.             // To do this, uncomment the following line of code.
  17.             // assemblyName = assemblyName.Replace("1.0.0.0", "2.0.0.0");
  18.  
  19.             // To use a different type from the same assembly,
  20.             // change the type name.
  21.             typeName = "Version2Type";
  22.         }
  23.  
  24.         // The following line of code returns the type.
  25.         typeToDeserialize = Type.GetType(String.Format("{0}, {1}",
  26.             typeName, assemblyName));
  27.  
  28.         return typeToDeserialize;
  29.     }
  30. }

Оффлайн EvgivachevАвтор темы

  • ADN OPEN
  • Сообщений: 16
  • Карма: 0
Assembly.GetExecutingAssembly() не использую потому, что десериализуемый тип "GraphAssembly.Graph" определён во внешней сборке

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Assembly.GetExecutingAssembly() не использую потому, что десериализуемый тип "GraphAssembly.Graph" определён во внешней сборке
Метод AppDomain.CurrentDomain.GetAssemblies() возвращает только сборки, которые УЖЕ загружены. Могу предположить, что при вызове вашей команды в автокаде не происходит загрузка этой самой внешней сборки.
Просто в начале команды вызовите метод Assembly.LoadFrom() с указанием этой самой сборки

Оффлайн EvgivachevАвтор темы

  • ADN OPEN
  • Сообщений: 16
  • Карма: 0
стр. 17 в классе MyBinder выводит
Цитировать
Не найден тип "System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[GraphAssembly.Node, GraphAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]" в сборке mscorlib
Не найден тип "System.Collections.Generic.List`1[[GraphAssembly.Section, GraphAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]" в сборке mscorlib
Поэтому предполагаю, что типы из "GraphAssembly" загрузить удалось

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
стр. 17 в классе MyBinder выводит
Цитировать
Не найден тип "System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[GraphAssembly.Node, GraphAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]" в сборке mscorlib
Не найден тип "System.Collections.Generic.List`1[[GraphAssembly.Section, GraphAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]" в сборке mscorlib
Поэтому предполагаю, что типы из "GraphAssembly" загрузить удалось
Вам лень попробовать мое предположение, добавив всего одну строчку?

Оффлайн EvgivachevАвтор темы

  • ADN OPEN
  • Сообщений: 16
  • Карма: 0
Ни в коем случае, дело в том, я пробовал уже этот метод, но сейчас ещё раз попробовал - результат тот же.
Ещё так попробовал:
Код - C# [Выбрать]
  1.  if (File.Exists(pathTofileGraph))
  2.                         {
  3.                             var myAssembly = Assembly.LoadFrom(
  4.                                 "R:\\04_Надстройки\\ЭОМ\\Схемы_Схема ВРУ Revit\\Рабочая\\InputDeviceAutoCAD\\InputDeviceAutoCAD\\bin\\Debug\\GraphAssembly.dll");
  5.                             var myAssName = myAssembly.FullName;
  6.                             var res = new GraphAssembly.Graph();
  7.                             using (var s = File.Open(pathTofileGraph, FileMode.Open))
  8.                             {
  9.                                 var bFormatter = new BinaryFormatter();
  10.                                 bFormatter.AssemblyFormat =
  11.                                     System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple;
  12.  
  13.                                 //bFormatter.Binder = new MyBinder(); // MyBinder class code given below
  14.  
  15.                                 try
  16.                                 {
  17.                                     res = (Graph)bFormatter.Deserialize(s);
  18.                                     var print = res.Print();
  19.                                 }
  20.                                 catch (SerializationException se)
  21.                                 {
  22.                                     Debug.WriteLine(se.Message);
  23.                                 }
  24.                             }
  25.                         }

Цитировать
Вызвано исключение: "System.Runtime.Serialization.SerializationException" в mscorlib.dll
Не удалось найти сборку "GraphAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null".

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Попробуйте Solution 1 отсюда - https://www.codeproject.com/Questions/181389/AppDomain-refuses-to-load-an-assembly
А также проверьте версии этой сборки

Оффлайн EvgivachevАвтор темы

  • ADN OPEN
  • Сообщений: 16
  • Карма: 0
Результат всё тот же. Версия сборки не менялась

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Результат всё тот же. Версия сборки не менялась
Попробуйте Assembly.LoadFile() вместо Assembly.LoadFrom()

Оффлайн EvgivachevАвтор темы

  • ADN OPEN
  • Сообщений: 16
  • Карма: 0
Всё так же

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Что-то вы недоговариваете =)) Придется, видимо, прикладывать нам тестовый проект. Идеи закончились

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13830
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Evgivachev,
Версия AutoCAD? Пытаетесь загрузить сборку GraphAssembly.dll с сетевого устройства?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн EvgivachevАвтор темы

  • ADN OPEN
  • Сообщений: 16
  • Карма: 0
Добрый день! Прошу прощения, что долго не отвечал.
AutoCAD 2016. Нет, GraphAssembly.dll на компьютере

Код - C# [Выбрать]
  1. using System;
  2. using System.Diagnostics;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Runtime.Serialization;
  6. using System.Runtime.Serialization.Formatters.Binary;
  7. using GraphAssembly;
  8.  
  9. namespace ConsoleApp20
  10. {
  11.     class Program
  12.     {
  13.         static void Main(string[] args)
  14.         {
  15.             var path = new DirectoryInfo(@"C:\Temp");
  16.             var pathTofileGraph = Path.Combine(path.FullName, "graphRevit.txt");
  17.             if (File.Exists(pathTofileGraph))
  18.             {
  19.                 var res = new GraphAssembly.Graph();
  20.                 using (var s = File.Open(pathTofileGraph, FileMode.Open))
  21.                 {
  22.                     var bFormatter = new BinaryFormatter();
  23.                     bFormatter.AssemblyFormat =
  24.                         System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Full;
  25.                     bFormatter.Binder = new MyBinder(); // MyBinder class code given below
  26.                     try
  27.                     {
  28.                         res = (Graph)bFormatter.Deserialize(s);
  29.                     }
  30.                     catch (SerializationException se)
  31.                     {
  32.                         Console.WriteLine(se.Message);
  33.                     }
  34.                 }
  35.             }
  36.             Console.WriteLine("ok");
  37.             Console.ReadKey();
  38.         }
  39.     }
  40.     internal sealed class MyBinder : SerializationBinder
  41.     {
  42.         public override Type BindToType(string assemblyName, string typeName)
  43.         {
  44.             Type ttd = null;
  45.             try
  46.             {
  47.                 var toassname = assemblyName.Split(',')[0];
  48.                 var asmblies = AppDomain.CurrentDomain.GetAssemblies();
  49.                 foreach (var ass in asmblies)
  50.                 {
  51.                     if (ass.FullName.Split(',')[0] == toassname)
  52.                     {
  53.                         var types = ass.GetTypes().Where(x => x.ContainsGenericParameters);
  54.  
  55.                         ttd = ass.GetType(typeName, false, true);
  56.                         if (ttd is null)
  57.                         {
  58.                             Debug.WriteLine($"Не найден тип \"{typeName}\" в сборке {toassname}");
  59.                         }
  60.                         else break;
  61.                     }
  62.                 }
  63.             }
  64.             catch (System.Exception e)
  65.             {
  66.                 Console.WriteLine(e.Message);
  67.             }
  68.             return ttd;
  69.         }
  70.     }
  71. }
  72.  
  73.  

Странно то, что этот код консольного приложения работает!

Оффлайн EvgivachevАвтор темы

  • ADN OPEN
  • Сообщений: 16
  • Карма: 0
Файлы для работы

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Так какая версия автокада?

Оффлайн EvgivachevАвтор темы

  • ADN OPEN
  • Сообщений: 16
  • Карма: 0
AutoCAD 2016

Оффлайн Привалов Дмитрий

  • ADN Club
  • *****
  • Сообщений: 534
  • Карма: 117
Подскажите, пожалуйста, с чем это может быть связано, как исправить?
Возможно дело в:
AutoCAD 2016 .NET 4.5

GraphAssembly7073.dll
System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.6")]

Найди/перекомпилируй файл GraphAssembly для .NET 4.5

Скорее всего в свежих версиях AutoCAD 2017-2018 (.NET 4.6) или AutoCAD 2019 (.NET 4.7) все будет ОК.

Оффлайн EvgivachevАвтор темы

  • ADN OPEN
  • Сообщений: 16
  • Карма: 0
Код - C# [Выбрать]
  1. internal sealed class MyBinder : SerializationBinder
  2.     {
  3.         public override Type BindToType(string assemblyName, string typeName)
  4.         {
  5.             Type ttd = null;
  6.             try
  7.             {
  8.                 var toassname = assemblyName.Split(',')[0];
  9.                 var asmblies = AppDomain.CurrentDomain.GetAssemblies();
  10.                 foreach (var ass in asmblies)
  11.                 {
  12.                     if (ass.FullName.Split(',')[0] == toassname)
  13.                     {
  14.                         var types = ass.GetTypes().Where(x => x.ContainsGenericParameters);
  15.  
  16.                         ttd = ass.GetType(typeName, false, true);
  17.                         if (ttd is null)
  18.                         {
  19.                             switch (typeName)
  20.                             {
  21.                                 case "System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[GraphAssembly.Node, GraphAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]":
  22.                                         ttd = typeof(Dictionary<string, Node>);
  23.                                         break;
  24.                                 case "System.Collections.Generic.List`1[[GraphAssembly.Section, GraphAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]":
  25.                                     ttd = typeof(List<Section>);
  26.                                     break;
  27.                                 case "System.Collections.Generic.KeyValuePair`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[GraphAssembly.Node, GraphAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]":
  28.                                     ttd = typeof(System.Collections.Generic.KeyValuePair<string,Node>);
  29.                                     break;
  30.                                 case "System.Collections.Generic.List`1[[GraphAssembly.Cable, GraphAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]":
  31.                                     ttd = typeof(List<Cable>);
  32.                                     break;
  33.                                 default:
  34.                                     Debug.WriteLine($"Не найден тип \"{typeName}\" в сборке {toassname}");
  35.                                     break;
  36.                             }
  37.                         }
  38.                         else break;
  39.                     }
  40.                 }
  41.             }
  42.             catch (System.Exception e)
  43.             {
  44.                 Debug.WriteLine(e.Message);
  45.             }
  46.             return ttd;
  47.         }
  48.     }
Придумал пока такой костыль, вроде помогло.
После компиляции для .NET 4.5 при отладке всё равно попадаем в блок switch.....

Спасибо за помощь!!!