Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум программистов _ .NET _ Динамически подключенная Dll и десериализация

Автор: Vitone 31:05:2008, 21:41

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

Сериализация:

CODE
SoapFormatter formatter = new SoapFormatter();
FileStream stream = File.Open(fileName, FileMode.Create);
FbdProgram tmp=new FbdProgram();
formatter.Serialize(stream, tmp);
stream.Close();


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


Фрагмент сохраненного 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

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

Автор: Pasha 1:06:2008, 08:44

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

Автор: Vitone 1:06:2008, 10:42

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

Вот привожу код:

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

}

Автор: Pasha 1:06:2008, 17:36

Vitone
Похоже, SoapFormatter не заморачивается с поиском библиотек, и тупо сам загружает их через Assembly.Load. А тот, в свою очередь, тупо отвечает что не может загрузить, т.к. не может найти файл на диске и сверить с уже загруженным. Пропиши в конфиге configuration/runtime
/assemblyBinding/probing/@privatePath к папке с длл-ками. Или просто помогай рантайму их резолвить, примерно так:

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;
            }
        }
    }
}
Звиняй, код на коленке написан.
ЗЫ. И еще, в десериализации ты зачем-то объект создаешь лишний раз:
            FbdProgram tmp=new FbdProgram();
            tmp = (FbdProgram)formatter.Deserialize(stream);

Автор: Vitone 1:06:2008, 18:19

Цитата(Pasha @ 1:06:2008 - 19:36) *
Пропиши в конфиге configuration/runtime
/assemblyBinding/probing/@privatePath к папке с длл-ками.


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

Цитата(Pasha @ 1:06:2008 - 19:36) *
Похоже, SoapFormatter не заморачивается с поиском библиотек, и тупо сам загружает их через Assembly.Load

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

Автор: Pasha 1:06:2008, 19:44

Цитата(Vitone @ 1:06:2008 - 20:19) *
А можно об этом поподробней? Никогда раньше не рограмил с использованием dll-ок.
Это секция конфига приложения, в которой можно прописать доп. пути для поиска сборок:
]]>http://forum.codeby.net/go.php?http://msdn.microsoft.com/en-us/library/823z9h8w.aspx]]>, и дальше по ссылками "How the Runtime Locates Assemblies"

Автор: Vitone 2:06:2008, 15:21

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

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

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

Автор: Vitone 2:06:2008, 20:00

Всё, разобрался, спасибо. Вот это мне помогло:
]]>http://forum.codeby.net/go.php?http://www.intuit.ru/department/pl/visualcsharp/9/6.html]]>
rolleyes.gif

Форум Invision Power Board (http://nulled.ws)
© Invision Power Services (http://nulled.ws)