Form aus Assembly - Form laden, schließen, wieder laden -> Fehler

M4st3r

Erfahrenes Mitglied
Hallo Leute,

folgendes Problem: Ich habe eine MDI-Anwendung die beim starten in einem Verzeichnis alle vorhandene DLL's durchgeht und in diesen nach Windows.Form's, die ein definiertes Interface implementiert haben, sucht. Entsprechende Forms werden in ein dictionary abgelegt, die Form-Caption wird in einen Treeview geschrieben der als Menü dient.

Soweit so gut. Wenn ich jetzt auf den Eintrag doppelklicke, dann öffnet sich die entsprechende Form als MDI-Child. Wenn ich die Form jetzt über das x schließe und erneut aufrufen will, bekomm ich folgende Exception:

Auf das verworfene Objekt kann nicht zugegriffen werden.
Objektname: [Name der Form]

Klingt so. als würde die Form "zerstört" werden wenn Sie geschlossen wird.

Wenn ich normalerweise eine Form anzeigen lassen will, funktioniert das ja mit

Code:
Form frm = new Form();

Wie mache ich das, wenn ich eine Form aus einer DLL laden?



Bin dankbar für jede Hilfe und jeden Tipp
 
Seltsam, jedesmal wenn ich hier poste, komm ich kurz danach selbst auf die Lösung...

Für alle die es interessiert:

Code:
public void OpenForm(Form frm)
        {

            Form form = (Form)Activator.CreateInstance(frm.GetType());

            form.WindowState = FormWindowState.Maximized;
            form.MdiParent = this;            
            form.Show();
        }

Als Parameter wird die Form aus dem dictionary übergeben. (Form)Activator.CreateInstance(frm.GetType()) erstellt, wie die Funktion schon sagt, eine neue Instanz des Types - et voilá, die Form geht auf, zu, auf, zu, auf...
 
Du liest die Forms aus deiner DLL und instanzierst sie vermutlich gleich. Mit
Code:
Form1 muh = new Form1();
instanzierst du die Form jedes Mal neu. Mit
Code:
muh.Show();
kannst du sie anzeigen.

Du hast insgesamt 2 Möglichkeiten:

1. Du instanzierst beim Durchgehen deiner Assembly alle Forms, was aber einen hohen Speicherverbrauch hat, vor allem, wenn nicht alle gebraucht werden. Zudem könntest (je nachdem wie komplex deine Forms sind) in ein Window-Handle-Problem laufen. Beim Klicken des Menüeintrags machst du dann ein Form1.Show(). Beim Closing-Event der jeweiligen Formen stoppst du den Schließen-Vorgang und machst einfach nur ein Form1.Hide(), sonst wird sie verworfen und du kannst nicht mehr darauf zugreifen (deine Fehlermeldung).

2 Du instanzierst die Form dann, wenn auf das entsprechende Menü geklickt wird. So ersparst du dir das Vorhalten der Forms (weniger Speicher), hat jedoch den Nachteil, dass es etwas länger dauert bis die Form sichtbar ist. Zudem müsstest du dir ein anderes Schema überlegen, wie du die Menüpunkte beschriftest etc.

Hoffe dir geholfen zu haben.
 
M4st3r hat gesagt.:
Seltsam, jedesmal wenn ich hier poste, komm ich kurz danach selbst auf die Lösung...

Für alle die es interessiert:

Code:
public void OpenForm(Form frm)
        {

            Form form = (Form)Activator.CreateInstance(frm.GetType());

            form.WindowState = FormWindowState.Maximized;
            form.MdiParent = this;            
            form.Show();
        }
Als Parameter wird die Form aus dem dictionary übergeben. (Form)Activator.CreateInstance(frm.GetType()) erstellt, wie die Funktion schon sagt, eine neue Instanz des Types - et voilá, die Form geht auf, zu, auf, zu, auf...

Das ist aber ein umständlicher Weg, weil du so immer mit zwei Objekten des gleichen Typs arbeitest. Das heißt doppelter Speicherverbrauch. Unnötig.
 
Auslesen tu ich den ganzen Spass so:

Code:
        public DllProvider(string path)
        {
            Assembly ass = Assembly.LoadFile(path);

            foreach (Type t in ass.GetTypes())
            {
                if (t.GetInterface("IForm") != null)
this._LoadedForms.Add((Form)Activator.CreateInstance(t));
            }
        }
Das heißt, ich habe eine Instanz der Form in meiner List<Form>. Mit (Form)Activator.CreateInstance(t) vor dem form.Show bekomm ich eine neue Instanz. Das ist dann das von dir angesprochene Speicher-Problem.

Im Form_Close Event habe ich schon versucht die Form auf Hide zu stellen, ebenso im Destructor. Beides hat nicht funktioniert. Jedesmal wurde die Form verworfen...

Ich weiß nicht ob es eine gute Alternative ist, aber ich bin jetzt soweit das ich mir keine Instanz der Form in die Collection lade sondern nur den Type. Beim MDIForm_Load lade ich mir die Types aus den DLL's die eine Form mit dem benötigten Interface habe. Die Menüeinträge erstelle ich, indem ich die List<Type>, in der die Types abgelegt sind, durchlaufe, mir kurz eine Instanz der Form hole, den Menüname auslese und die Form wieder über frm.Dispose kaputt mache.
 

Neue Beiträge

Zurück