Динамически подключенная Dll и десериализация

Тема в разделе ".NET", создана пользователем Vitone, 1 июн 2008.

  1. Vitone

    Vitone Гость

    У меня такая проблемма. Существует иеархия классов, при чем базовый класс и большое множество производных от него классов раскиданы по разным dll-кам (в одной - сколько угодно производных классов). И мне необходимо сохранять состояние классов (использую SOAP сериализацию). Так вот, если эти dll-ки подключаю статически, то все нормально, но когда динамически - возникает ошибка при попытке десериализировать, при чем на этапе разбора элементов XML файла.

    Сериализация:
    [codebox] SoapFormatter formatter = new SoapFormatter();
    FileStream stream = File.Open(fileName, FileMode.Create);
    FbdProgram tmp=new FbdProgram();
    formatter.Serialize(stream, tmp);
    stream.Close();
    [/codebox]

    Десериализация:
    [codebox] Stream stream = File.Open(fileName, FileMode.Open);
    SoapFormatter formatter = new SoapFormatter();
    FbdProgram tmp=new FbdProgram();
    tmp = (FbdProgram)formatter.Deserialize(stream);
    stream.Close();
    [/codebox]

    Фрагмент сохраненного XML файла:
    <a2:MUL_INT id="ref-10" xmlns:a2="http://schemas.microsoft.com/clr/nsassem/FBDVisualBlocks.VisualBlocks/FBDVisualBlocks%2C%20Version%3D1.0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Db98b95bcb02affd6">

    Ошибка происходит при десериализации на строчке:
    tmp = (FbdProgram)formatter.Deserialize(stream);

    При этом она имеет следующий вид:

    An unhandled exception of type 'System.Runtime.Serialization.SerializationException' occurred in System.Runtime.Serialization.Formatters.Soap.dll

    Additional information: Parse Error, no assembly associated with Xml key a2:http://schemas.microsoft.com/clr/nsassem/FBDVisualBlocks.VisualBlocks/FBDVisualBlocks%2C%20Version%3D1.0.0.0%2C%20Culture%3Dneutral%2C%20PublicKeyToken%3Db98b95bcb02affd6 MUL_INT

    Большое спасибо!
     
  2. Pasha

    Pasha Гость

    Vitone
    Динамически - это как?
     
  3. Vitone

    Vitone Гость

    Библиотеки подключаются так: ищутся все dll-ки в заданном каталоги и с заданным атрибутом:

    Вот привожу код:
    [codebox] public void LoadDlls(string path)
    {
    DirectoryInfo Dir = new DirectoryInfo(path);
    FileInfo[] files = Dir.GetFiles("*.dll");
    foreach (FileInfo file in files)
    {
    a = Assembly.LoadFrom(Application.StartupPath + "\\" + path+"\\"+file.Name/*.Substring(0, file.Name.Length - 4)*/);
    _types = a.GetTypes();
    foreach (Type type in _types)
    {
    ListOfTypes.Add(type);
    }
    }

    }
    [/codebox]
     
  4. Pasha

    Pasha Гость

    Vitone
    Похоже, SoapFormatter не заморачивается с поиском библиотек, и тупо сам загружает их через Assembly.Load. А тот, в свою очередь, тупо отвечает что не может загрузить, т.к. не может найти файл на диске и сверить с уже загруженным. Пропиши в конфиге configuration/runtime
    /assemblyBinding/probing/@privatePath к папке с длл-ками. Или просто помогай рантайму их резолвить, примерно так:
    Код (Text):
    using System;
    using System.IO;
    using System.Reflection;
    using System.Runtime.Serialization.Formatters.Soap;

    namespace ConsoleApplication2
    {
    class Program
    {
    private static Assembly sampleAssembly;

    static void Main(string[] args)
    {
    sampleAssembly = Assembly.LoadFrom(@"D:\Projects\sl1\ClassLibrary1\bin\Debug\ClassLibrary1.dll");

    AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);

    Stream stream = File.Open(@"D:\temp.txt", FileMode.Open);
    SoapFormatter formatter = new SoapFormatter();
    object tmp = formatter.Deserialize(stream);
    stream.Close();
    }

    static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
    {
    if (args.Name == sampleAssembly.FullName)
    {
    return sampleAssembly;
    }
    else
    {
    return null;
    }
    }
    }
    }
    Звиняй, код на коленке написан.
    ЗЫ. И еще, в десериализации ты зачем-то объект создаешь лишний раз:
    Код (Text):
                FbdProgram tmp=new FbdProgram();
    tmp = (FbdProgram)formatter.Deserialize(stream);
     
  5. Vitone

    Vitone Гость

    А можно об этом поподробней? Никогда раньше не рограмил с использованием dll-ок. А за помощь спасибо, сейчас проверю!

    Твоя правда, Pasha, SoapFormatter не ищет dll-ки в моей папке, а ищет в той, где сам ехе-шник. Но мне очень желательно, чтоб эти dll-ки были в отдельной папке, поскольку предполагается, что их количество будет расти, и, возможно писть их будет кто-то другой.
     
  6. Pasha

    Pasha Гость

    Это секция конфига приложения, в которой можно прописать доп. пути для поиска сборок:
    http://msdn.microsoft.com/en-us/library/823z9h8w.aspx, и дальше по ссылками "How the Runtime Locates Assemblies"
     
  7. Vitone

    Vitone Гость

    Создал конфигурационный файл Program.exe.config и поместил в папку с экзешником (bin\Debug), прописал в нем такие строчки:

    <?xml version="1.0"?>
    <configuration>
    <runtime>
    <assemblyBinding>
    <probing privatePath="Blocks;"/>
    </assemblyBinding>
    </runtime>
    </configuration>

    Но SoapFormatter все равно не находит сборки, только в папке экзешника.
    Что я не так сделал?
     
  8. Vitone

    Vitone Гость

Загрузка...

Поделиться этой страницей