Autor Beitrag
LL0rd
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19



BeitragVerfasst: Di 11.12.07 11:35 
Hallo Leute,

ich habe da ein Problem mit einem Programm. Ich habe eine Server Anwendung, die Berechnungen ausführen soll. Welche Berechnungen genau ausgeführt werden, weiß das Programm nicht. Es bekommt immer binär serialisierte Daten sowie eine DLL Datei, in der sowohl die Klassen stehen, die Serialisiert wurden, als auch wie mit den Daten gerechnet werden soll. Doch nun komme ich zu meinem eigentlichen Problem:

In den ersten Tests habe ich nur getestet, ob der Server die Verbindung tatsächlich annimmt, alles ausrechnet und die Daten wieder an den Client schicken kann. Doch nun war die Zeit von mehreren Clients gekommen, die gleichzeitig mit dem Server arbeiten. Aus diesem Grund überträgt der Client seine DLL Datei (ist bei jedem Client eine andere) und der Server speichert die DLL Datei unter der Guid + ".dll". Doch genau hier habe ich einen Fehler festgestellt. Ich konnte die Daten zwar deserialisieren, konnte mit dennen aber nicht mehr arbeiten. Ich habe immer den Fehler bekommen: "Apfel kann nicht zu Apfel gecastet werden". Habe ich den Namen der DLL Datei wieder auf den Ursprünglichen Namen gesetzt, so ging wieder alles.

Kann mir von euch jemand sagen, wie es trotz dem Umbennen so hinbekommen kann, dass ich mit den Daten arbeiten kann? Der dll Datei kann ich keinen eigenen Namen geben, da diese vom User abhängt.
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Di 11.12.07 14:01 
Ich kann mir nicht wirklich vorstellen, wie das Umbenennen der Assembly Probleme machen soll, aber wenn es so ist, dann lass die Umbenennung doch einfach und schieb die Dll stattdessen in ein temporäres Verzeichnis.
Achja, wenn "Apfel nicht in Apfel" konvertiert werden kann, kommen die beiden gleichnamigen Typen ja wohl eindeutig aus zwei verschiedenen Assemblies. Schau doch mal nach, welche das sein sollen.
LL0rd Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19



BeitragVerfasst: Di 11.12.07 14:10 
Aber genau das passiert leider.

ausblenden C#-Quelltext
1:
2:
assUser = Assembly.LoadFrom(Filename);
retImObj = (abstrakte Klasse)assUser.CreateInstance("User.Apfel");


Mit diesem Code erstelle ich ein neues Objekt der Klasse Apfel. Ist Filename nun nicht "Apfel.dll", sondern "User1Apfel.dll" oder "User1/Apfel.dll", so entspricht so entspricht ein serialisierter Apfel nicht dem, der gerade erstellt wurde und kann auch nicht gecastet werden.

Du meintest das mit dem tmp. Verzeichnis, doch User1/Apfel.dll, oder?
Kha
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 3803
Erhaltene Danke: 176

Arch Linux
Python, C, C++ (vim)
BeitragVerfasst: Di 11.12.07 15:13 
Wie ich schon sagte, schau erst einmal, woher deine zwei Äpfel kommen, denn offensichtlich nicht vom gleichen Fleck. Type.Assembly.Location
LL0rd Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19



BeitragVerfasst: Fr 14.12.07 09:07 
Also meine beiden Äpfel kommen zwar vom gleichen Baum, werden jedoch von zwei verschiedenen Bauern verkauft.

Und hier sehe ich auch schon, wo mein Fehler anfängt.

Type.Assembly.Location des original Typs hat mir eine "user.dll" gemeldet, die ich zum Testen per Hand rüberkopiert habe. Die DLL entspricht komplett (auch der Dateiname) der DLL Datei, mit der die Testdaten serialisiert wurden. So wie es für mich aussieht, greift C# schon während des deserialisierens einfach so auf die DLL zu, denn als ich die user.dll gelöscht habe, erschien aufeinmal ein Fehler beim Deserialisieren:

ausblenden Quelltext
1:
Unable to find assembly 'user, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'.					


Dann verstehe ich auch, wieso der Typ nicht mit dem übereinstimmt, mit dem die Datei serialisiert wurde. Aber wie könnte ich das umgehen? D.h. dass ich z.B. mit der user.dll in einer Anwendung serialisiere und mit wdufghsf.dll unter einer anderen deserialisiere?
LL0rd Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 19



BeitragVerfasst: Fr 14.12.07 09:39 
Für eine .DLL habe ich es bereits gelöst:


ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(MyResolveEventHandler);

        private Assembly MyResolveEventHandler(object sender, ResolveEventArgs args)
        {
            Assembly a = Assembly.LoadFrom("abcUser.exe");
            return a;
        }


Wenn ich es richtig verstanden habe, dann wird ein Resolve "Pfad" hinzugefügt, der angibt, in welchen Dateien nach dem Typ user.Apfel gesucht werden soll. Nun kann es aber durchaus vorkommen, dass der Typ user.Apfel in mehreren DLL Dateien deklariert wurde, die zur selben Laufzeit geladen werden. Dann kann das System doch nicht unterscheiden, welche DLL zum Laden benutzt werden soll. Gibt es eine Möglichkeit anzugeben, dass Daten mit einer bestimmten Assembly (DLL) deserialisiert werden?