Avatar billede dn666 Nybegynder
03. oktober 2005 - 15:42 Der er 32 kommentarer og
1 løsning

load en dll runtime

Jeg har en app på nuværende tidspunkt med en masse "plugins" i deres eget namespace.

Nu vil jeg gerne have disse "plugins" ud af min main app.
så jeg har mine plugins i hver deres assenbly, med hver deres app.config. osv. så det er muligt at loade/unloade dem hvis der skal rettes i dem uden at hele min main app skal lukkes ned..
Avatar billede arne_v Ekspert
03. oktober 2005 - 15:48 #1
CommonInterface o  = Assembly.Load("YourDll").CreateInstance("YourClass");
Avatar billede arne_v Ekspert
03. oktober 2005 - 15:49 #2
jeg glemte cast:

CommonInterface o  = (CommonInterface)Assembly.Load("YourDll").CreateInstance("YourClass");
Avatar billede dn666 Nybegynder
03. oktober 2005 - 17:00 #3
Cool.. :)

Jeg har testet den men contructoren bliver ikke kaldt på mit Plugin object..

Jeg har lavet 3 asseblies:

PluginManager, har kun 1 interface:


namespace PluginManager
{
    public interface IPlugin
    {
        string Name {get;set;}
    }
}

Selve plugin'et:

namespace TestPlugin1
{
    public class TestPlugin1 : IPlugin
    {
        private string name;
        public TestPlugin1()
        {
            this.name = "TestPlugin1";
        }

       

        public string Name
        {
            get { return name; }
            set { name = value; }
        }
    }
}


og så min main app's main:
        static void Main(string[] args)
        {
            string dllName = "TestPlugin1.dll";
            string className = "TestPlugin1.TestPlugin1";
            IPlugin plugin = (IPlugin)Assembly.LoadFile(dllName).CreateInstance(className);
            Console.WriteLine("plugin : " + plugin);
            Console.WriteLine("name  : " + plugin.Name);
            Console.ReadLine();
        }

burde CreateInstance ikke kalde konstructorem på mit plugin ??
det gør den ihverfald ikke.. ??
Avatar billede arne_v Ekspert
03. oktober 2005 - 17:10 #4
det virker fint hos mig

C:\>plugintest
plugin : TestPlugin1.TestPlugin1
name  : TestPlugin1

set da rigtigt ud
Avatar billede dn666 Nybegynder
03. oktober 2005 - 17:18 #5
sry !!!
en fejl 40.01 (TestPlugin1 var ikke rebuilded) ;)

kan du ikke svare så du kan få lidt point... :)
Avatar billede arne_v Ekspert
03. oktober 2005 - 17:19 #6
gerne
Avatar billede cjensen Nybegynder
05. oktober 2005 - 17:58 #7
bare lige for en ordens skyld: din dll bliver ikke unloaded - den ligger stadig i hukkomelsen. Det er muligt du ikke refererer til den fra din main-app. Hvis den skal unloades korrekt, så skal du over i noget teknik a' la fusion.
Avatar billede arne_v Ekspert
05. oktober 2005 - 18:05 #8
hvis man skal unloade skal de loades i sit eget app domain fordi så kan man
onloade hele app domain
Avatar billede cjensen Nybegynder
05. oktober 2005 - 18:10 #9
jeps - det er det fusion gør.
Her er lidt info om hvorfor:
http://blogs.msdn.com/jasonz/archive/2004/05/31/145105.aspx
Avatar billede arne_v Ekspert
05. oktober 2005 - 18:22 #10
Jeg troede at fusion var et produkt og det er jo ikke det store besvær at skrive
de 3 linier som brug af app domain kræver
Avatar billede cjensen Nybegynder
05. oktober 2005 - 18:58 #11
fusion bliver brugt af IIS (som jo loader og unloader assemblies ved ændringer)
kald på tværs af af domains sker ikke direkte. Det kan fx gøres vha remoting, proxies eller kopiering af objekter mellem appdomains (i alle tilfælde på bekostning af performance).

http://msdn2.microsoft.com/en-us/library/w124b5fa

(det er lidt en tilsnigelse den med de 3 liniers kode ;-)
Avatar billede arne_v Ekspert
05. oktober 2005 - 19:02 #12
2 linier til at loade objekt i eget app domain:

AppDomain d = AppDomain.CreateDomain("MyDomain");
object o = d.CreateInstanceAndUnwrap("MyAssembly", "MyClass");

1 linie til at unloade:

AppDomain.Unload(d);
Avatar billede cjensen Nybegynder
09. oktober 2005 - 10:49 #13
LOL

Det er da også uden det mindst fejlkontrol (i.e. exception-handling). Ikke noget jeg personligt vil anbefale.
Avatar billede arne_v Ekspert
09. oktober 2005 - 21:25 #14
jeg vil også anbefale exception handling

men jeg siger ikke at det kræver 10 linier at lave en division i C# med begrundelsen
at der skal exception handling til
Avatar billede dn666 Nybegynder
11. september 2006 - 16:15 #15
Hehe.

sidder lige og leger med unload af appdomain og finder denne tråd igen :).
uanseet exception handling. virker dette ikke som jeg vil ha det til..

AppDomain d = AppDomain.CreateDomain("MyDomain");
object o = d.CreateInstanceAndUnwrap("MyAssembly", "MyClass");
(o as IPlugin).Test;
AppDomain.Unload(d);


Assembly bliver loaded og Test bliver executed (Printer "hello")
AppDomain.Unload(d);
unloader ikke jeg har kunnet finde rundt omkring at CreateInstanceAndUnwrap loader objected i både det nye appdomain & det default. det har noget med referencer og Remoting at gøre, men jeg er ikke 100.

Hvad jeg egentlig prøver er dette:

AppDomain domain = AppDomain.CreateDomain("tmpDomain");       
Assembly assembly = domain.Load(dllBytes);
IPlugin plugin = (IPlugin)assembly.CreateInstance("TestNamespace.TestPlugin");
ITask task = null; // dummy
plugin.RefreshDeliveries(task);
AppDomain.Unload(domain);

dllBytes is a byte[] with the dll file loaded in mem. comming in as an arg to the method.

dette resulterer i samme situation..

jeg får "Insufficient state to deserialize the object.  More information is needed."
hvis jeg har dll'en liggende alle andre steder end bin/Debug folderen

Hvordan kan man gøre det "rigtigt" så dll'en kan slettes efter unload og ikke nødvendigvis behøver at ligge i samme folder som de andre dll'er...
Avatar billede dn666 Nybegynder
11. september 2006 - 16:15 #16
sry der er lidr engels indblandet.. :)
Avatar billede arne_v Ekspert
12. september 2006 - 05:09 #17
lidt mystisk - jeg har fungerende eksempler som loader en klasse med samme navn
Avatar billede dn666 Nybegynder
12. september 2006 - 10:45 #18
Jeg ar fundet frem til at når du laver et nyt domain og loader dll'en fra det domain bliver den loaded i både de default og det nye.

Jeg har så lavet en "wrapper" til at håndtere mine remote loadede dll'er
en LocalLoader og en RemoteLoader
Jeg laver så et doamin pr, dll, via LocalLoader, den loader så min RemoteLoader, som loader dll'en.. puuhhh..

Når jeg så unloader releaser den perfekt.
Avatar billede cjensen Nybegynder
12. september 2006 - 20:01 #19
Det er også en måde at løse det på.

Og til Arne så fastholder jeg at det er en tilsnigelse med de 3 linier kode. Netop med de problemstillinger der opstår ved kald imellem domains.
Din løsning i indlæg #1/2 er den forbindelse lidt tyndt.
Avatar billede arne_v Ekspert
13. september 2006 - 04:01 #20
mystisk - jeg kan ikke genskabe problemet - undtagen når jeg putter debug kode ind
Avatar billede arne_v Ekspert
13. september 2006 - 04:02 #21
using System;

public class X : MarshalByRefObject
{
    private static int k = 0;
    public override string ToString()
    {
        k++;
        return "x1: k=" + k;
    }
}
Avatar billede arne_v Ekspert
13. september 2006 - 04:02 #22
using System;

public class X : MarshalByRefObject
{
    private static int k = 0;
    public override string ToString()
    {
        k++;
        return "x2: k=" + k;
    }
}
Avatar billede arne_v Ekspert
13. september 2006 - 04:02 #23
using System;
using System.Reflection;
using System.Diagnostics;

namespace E
{
    public class MainClass
    {
        public static void LoadEvent(object sender, AssemblyLoadEventArgs args)
        {
            Console.WriteLine("Load : " + ((AppDomain)sender).FriendlyName + " <- " + args.LoadedAssembly.FullName);
        }
        public static void Dump(AppDomain d)
        {
            Console.WriteLine(d.FriendlyName + " contains:");
            foreach(Assembly a in d.GetAssemblies())
            {
                Console.WriteLine("-" + a.FullName);
            }
        }
        public static void Test(string fnm)
        {
            AppDomain d = AppDomain.CreateDomain("MyDom");
            //d.AssemblyLoad += new AssemblyLoadEventHandler(LoadEvent); // causes MyDom to load loader.exe - comment out to avoid
            object x  = d.CreateInstanceAndUnwrap(fnm, "X");
            Console.WriteLine(x);
            Console.WriteLine(x);
            Console.WriteLine(x);
            Dump(AppDomain.CurrentDomain);
            //Dump(d); // causes loader.exe to load x*.dll - comment out to avoid
            AppDomain.Unload(d);
        }
        public static void Main(string[] args)
        {
            AppDomain.CurrentDomain.AssemblyLoad += new AssemblyLoadEventHandler(LoadEvent);
            Test("x1");
            Test("x2");
            Test("x1");
            Test("x2");
        }
    }
}
Avatar billede arne_v Ekspert
13. september 2006 - 04:02 #24
csc /t:library x1.cs
csc /t:library x2.cs
csc /t:exe loader.cs
loader
Avatar billede arne_v Ekspert
13. september 2006 - 04:03 #25
C:\>testload

C:\>csc /t:library x1.cs
Microsoft (R) Visual C# .NET Compiler version 7.10.6001.4
for Microsoft (R) .NET Framework version 1.1.4322
Copyright (C) Microsoft Corporation 2001-2002. All rights reserved.


C:\>csc /t:library x2.cs
Microsoft (R) Visual C# .NET Compiler version 7.10.6001.4
for Microsoft (R) .NET Framework version 1.1.4322
Copyright (C) Microsoft Corporation 2001-2002. All rights reserved.


C:\>csc /t:exe loader.cs
Microsoft (R) Visual C# .NET Compiler version 7.10.6001.4
for Microsoft (R) .NET Framework version 1.1.4322
Copyright (C) Microsoft Corporation 2001-2002. All rights reserved.


C:\>loader
x1: k=1
x1: k=2
x1: k=3
loader.exe contains:
-mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-loader, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
x2: k=1
x2: k=2
x2: k=3
loader.exe contains:
-mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-loader, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
x1: k=1
x1: k=2
x1: k=3
loader.exe contains:
-mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-loader, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
x2: k=1
x2: k=2
x2: k=3
loader.exe contains:
-mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-loader, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
Avatar billede arne_v Ekspert
13. september 2006 - 04:03 #26
bemærk dog de 2 udkommenterede linier i loader
Avatar billede cjensen Nybegynder
13. september 2006 - 08:53 #27
Arne - til gengæld tager jeg hatten af for dit end-to-end eksempel!

Jeg har ikke nogen problem med at undlade at udkommentere:
d.AssemblyLoad += new AssemblyLoadEventHandler(LoadEvent); // causes MyDom to load loader.exe - comment out to avoid

men Dump gør at loader.exe bliver loaded.... lidt sært.... muligvis kan det have noget at gøre med, at de assemblies der bliver hentet fra MyDom bliver eksekveret i loader.exe's domain når "FullName" property'en bliver skrevet i Console.WriteLine("-" + a.FullName);
Avatar billede cjensen Nybegynder
13. september 2006 - 12:43 #28
Her er lidt mere:
build.bat
csc /t:library xbase.cs
csc /t:library x1.cs /r:xbase.dll
csc /t:library x2.cs /r:xbase.dll
csc /t:exe loader.cs /r:xbase.dll
Avatar billede cjensen Nybegynder
13. september 2006 - 12:44 #29
xbase.cs

using System;
using System.Reflection;
using System.Diagnostics;

public interface IDebug
{
    void Debug();
}

public class AppDomainLog
{
    public static void LoadEvent(object sender, AssemblyLoadEventArgs args)
    {
        Console.WriteLine("Load : " + ((AppDomain)sender).FriendlyName + " <- " + args.LoadedAssembly.FullName);
    }
}

public class XBase : MarshalByRefObject, IDebug
{
    public void Debug()
    {
          AppDomain d = AppDomain.CurrentDomain;
          Console.WriteLine(d.FriendlyName + " contains:");
        foreach(Assembly a in d.GetAssemblies())
        {
                Console.WriteLine("-" + a.FullName);
        }
      }
}
Avatar billede cjensen Nybegynder
13. september 2006 - 12:44 #30
x1.xs

using System;
using System.Reflection;
using System.Diagnostics;
     
public class X : XBase
{
    private static int k = 0;
    public override string ToString()
    {
        k++;
        return "x1: k=" + k;
    }
}
Avatar billede cjensen Nybegynder
13. september 2006 - 12:44 #31
x2.cs

using System;
using System.Reflection;
using System.Diagnostics;

public class X : XBase
{
    private static int k = 0;
    public override string ToString()
    {
        k++;
        return "x2: k=" + k;
    }

}
Avatar billede cjensen Nybegynder
13. september 2006 - 12:45 #32
loader.cs

using System;
using System.Reflection;
using System.Diagnostics;
using System.Runtime.Remoting;

namespace E
{
    public class MainClass
    {
        public static void LoadEvent(object sender, AssemblyLoadEventArgs args)
        {
            Console.WriteLine("Load : " + ((AppDomain)sender).FriendlyName + " <- " + args.LoadedAssembly.FullName);
        }
        public static void Dump(AppDomain d)
        {
            Console.WriteLine(d.FriendlyName + " contains:");
            foreach(Assembly a in d.GetAssemblies())
            {
                Console.WriteLine("-" + a.FullName);
            }
        }
        public static void Test(string fnm)
        {
              Console.WriteLine("\nTest: " + fnm);
            AppDomain d = AppDomain.CreateDomain("MyDom");
            d.AssemblyLoad += new AssemblyLoadEventHandler( AppDomainLog.LoadEvent);

            object x  = d.CreateInstanceAndUnwrap(fnm, "X");
            Console.WriteLine(x);
            Console.WriteLine(x);
            Console.WriteLine(x);
            Dump(AppDomain.CurrentDomain);
            (x as IDebug).Debug();
            AppDomain.Unload(d);
        }
        public static void Main(string[] args)
        {
            AppDomain.CurrentDomain.AssemblyLoad += new AssemblyLoadEventHandler(LoadEvent);
            Test("x1");
            Test("x2");
            Test("x1");
            Test("x2");
        }
    }
}
Avatar billede cjensen Nybegynder
13. september 2006 - 12:46 #33
og output:

Load : loader.exe <- xbase, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null

Test: x1
Load : MyDom <- x1, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
x1: k=1
x1: k=2
x1: k=3
loader.exe contains:
-mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-loader, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
-xbase, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
MyDom contains:
-mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-xbase, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
-x1, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null

Test: x2
Load : MyDom <- x2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
x2: k=1
x2: k=2
x2: k=3
loader.exe contains:
-mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-loader, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
-xbase, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
MyDom contains:
-mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-xbase, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
-x2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null

Test: x1
Load : MyDom <- x1, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
x1: k=1
x1: k=2
x1: k=3
loader.exe contains:
-mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-loader, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
-xbase, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
MyDom contains:
-mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-xbase, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
-x1, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null

Test: x2
Load : MyDom <- x2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
x2: k=1
x2: k=2
x2: k=3
loader.exe contains:
-mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-loader, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
-xbase, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
MyDom contains:
-mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-xbase, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
-x2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester