Auf DLL in AppDomain zugreifen

  • Hiho,


    ich bin wiedermal an einem Punkt angelangt, andem ich nicht weiterkomme.


    Ich versuche mich gerade an Plugins in C#. Das klappt auch ganz gut:


    [cs]
    Assembly assembly = Assembly.LoadFrom("Plugin.dll");


    foreach (Type type in assembly.GetTypes())
    {
    Type typeInterface = type.GetInterface("PluginTest.IPlugin", true);


    if (typeInterface != null)
    {
    IPlugin plugin = (IPlugin)Activator.CreateInstance(type);


    plugin.SayHello();


    break;
    }
    }
    [/cs]




    Nun möchte ich aber gerne Plugins zur Laufzeit nicht nur laden sondern auch entladen können. Geladene Assemblys werden erst entladen, wenn die gesammte AppDomain entladen wird.


    Also dachte ich mir: Jedes Plugin in eine eigene AppDomain. Das klappt ebenfalls alles ganz gut.


    [cs]AppDomain appDomain = AppDomain.CreateDomain("Plugin 1");


    appDomain.DoCallBack(new CrossAppDomainDelegate(delegate()
    {
    Assembly asm = Assembly.LoadFrom(@"Plugin.dll");


    IPlugin plugin;


    foreach (Type type in asm.GetTypes())
    {
    Type intface = type.GetInterface("PluginTest.IPlugin", true);
    if (intface != null)
    {
    plugin = (IPlugin)Activator.CreateInstance(type);
    plugin.SayHello();
    break;
    }
    }


    }));


    AppDomain.Unload(appDomain);[/cs]


    Nur möchte ich natürlich auch auf das Plugin zugreifen können. Das geht aber im Moment nur über den Delegate. Und sobald der delegate durch ist, ist alles was Instanzen war vergessen.


    Wie greife ich also auf die DLL in der AppDomain zu?


    Ich hab mir dazu schon dieses Tutorial angeschaut, was im Endeffekt genau das realisiert, aber ich verstehe es nicht ...
    http://get-the-solution.net/in…23-Plugins-mit-AppDo.html


    Gruß
    florian0

  • Ich will außerhalb der AppDomain auf die DLL zugreifen, bzw z.B. die Funktion SayHello aufrufen.


    Ich hab inzwischen sogar geschafft eine Instanz des Interfaces außerhalb der AppDomain zu erzeugen:



    Edit: Auf jeden Fall sehr sehr tricky das Ganze ... Ich hab gerade rausgefunden, das zu den Tutorial eine komplette Projektmappe zum Download angeboten wird. Die werde ich mir morgen mal antun.


    Edit2: Ich weis nun wie ich die nötigen Infos aus der AppDomain holen kann. Über SetData kann ich Daten in die AppDomain schreiben und diese später mit GetData wieder abholen. Allerdings will das nicht so wie ich will:
    [cs]
    AppDomain appDomain = AppDomain.CreateDomain("Plugin 1");


    appDomain.DoCallBack(new CrossAppDomainDelegate(delegate()
    {
    Assembly asm = Assembly.LoadFrom(@"Plugin.dll");


    String pluginName = String.Empty;


    foreach (Type type in asm.GetTypes())
    {
    Type intface = type.GetInterface("PluginTest.IPlugin", true);
    if (intface != null)
    {
    pluginName = type.FullName;


    break;
    }
    }


    appDomain.SetData("PluginName", pluginName);


    }));


    String name = (String)appDomain.GetData("PluginName");


    IPlugin plugin = (IPlugin)appDomain.CreateInstanceFromAndUnwrap("Plugin.dll", name);
    plugin.SayHello();


    AppDomain.Unload(appDomain);
    [/cs]


    Sobald ich jedoch SetData in den Callback packe, gehts netmehr:

    Code
    1. Der Typ "PluginTest.Program+<>c__DisplayClass1" in Assembly "PluginTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" ist nicht als serialisierbar gekennzeichnet.


    Was soll ich da als Serialisierbar kennzeichnen?

  • Ich hab das mit dem Serializing versucht. Ich hab alles als Serializeable gekennzeichnet, von ISerializeable erben lassen, etc. Serializing hasst mich :D
    Wenn du Lust und Zeit hast, könnten wir daran noch ein bischen tüfteln. Mich würde auf jeden Fall interessieren, warum das mit Callback nicht klappt.


    Ich habs anders gelöst:


    [headline]Lösung[/headline]


    Mit Callback will es einfach nicht klappen. Daher nutze ich als Alternative die Klassen AppDomainSetup und AppDomainInitializer.