Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

[.NET] Dynamisch laden van assemblies

Pagina: 1
Acties:

  • whoami
  • Registratie: December 2000
  • Laatst online: 17:54
Ik ben een applicatie aan het bouwen waar er verschillende types dynamisch moeten kunnen geladen worden. De types die moeten geladen worden, staan gespecifieerd in een configfile, en worden geladen door een 'factory' class.

De configfile ziet er bv zo uit:
code:
1
2
3
4
<typetoload>
    <assemblyname>f:\mydirectory\myassembly.dll</assemblyname>
    <typename>mytype</typename>
</typetoload>


In de factory class ga ik de XML configuration file gaan lezen, en met die informatie ga ik dan de objecten gaan laden.
Dit doe ik als volgt:
code:
1
2
3
Assembly asm = Assembly.LoadFrom (assemblyName);
// assemblyName is hier f:\mydirectory\myassembly.dll
object o = asm.CreateInstance ( typeName, true, BindingFlags.Default, .... );

Tot hiertoe geen probleem, de objecten worden goed geladen.
Echter, er treedt een probleem op als het object dat ik wil inladen een reference heeft naar een andere custom assembly die zich niet in de GAC bevind; die referenced assembly bevindt zich echter wel in dezelfde directory als de assembly die ik wil laden (in m'n voorbeeld dus f:\mydirectory).
Dit probleem treedt ook enkel op als de configuratie-file waar ik eerder over sprak niet in dezelfde directory staat als de assemblies (f:\mydirectory dus). Staat die configuratie file wel in die directory, dan heb ik het probleem niet.
Ik heb ook gezien dat de 'CurrentDirectory' de directory is waar de configuratie-file staat. Vandaar dus dat die referenced assembly wel gevonden wordt als m'n config file in diezelfde directory staat.

Nu heb ik gezien dat er een aantal events bestaan die zouden moeten getriggered worden als een assembly niet gevonden wordt bij het laden:
Assembly.ModuleResolve
AppDomain.TypeResolve
AppDomain.AssemblyResolve

Nu had ik het idee om een eventhandler te 'subscriben' aan deze events, zodat ik dan zelf naar die assembly kan gaan zoeken, maar blijkbaar worden deze events in mijn geval zelfs niet getriggered.

Heeft er hier iemand ervaring met dergelijke dingen, misschien heeft iemand een idee of een gouden tip.

https://fgheysels.github.io/


  • 6K
  • Registratie: September 2002
  • Laatst online: 19-01 15:07

6K

is ook zo...

ik ben waarschijnlijk een enorme spuit 11 nu, maar ik heb eens iets gelezen over dynamische verwijzing naar je appname.exe.config file. Als je dat zou kunnen realiseren heb je daar dus altijd beschikking over en zou het probleem niet meer optreden?

heb ik thuis ergens in 1 of ander boek staan meen ik allemaal (MCAD training kit - XML webservices and server components)

٩(͡๏̯͡๏)۶ ٩(●̮̮̃•̃)۶


  • whoami
  • Registratie: December 2000
  • Laatst online: 17:54
Ik heb gezien dat je in een AppDomain de PrivateBinPathProbe directory kunt specifieren. Echter, je kan die slechts specifieren voor de eerste assembly ingeladen wordt.
Ik vermoed dat ik m'n probleem kan oplossen door deze propertie te zetten, echter, dan zou ik iedere assembly die ik dynamisch inlaad in een apart AppDomain moeten inladen, aangezien die probing-directory in principe voor iedere assembly anders kan zijn (het hangt ervan af waar die assembly staat).
Het lijkt me ook niet gewenst om voor iedere assemblly een apart AppDomain te gaan maken.

https://fgheysels.github.io/


  • whoami
  • Registratie: December 2000
  • Laatst online: 17:54
6K schreef op 29 september 2004 @ 10:39:
ik ben waarschijnlijk een enorme spuit 11 nu, maar ik heb eens iets gelezen over dynamische verwijzing naar je appname.exe.config file. Als je dat zou kunnen realiseren heb je daar dus altijd beschikking over en zou het probleem niet meer optreden?
Die assemblies/types die moeten geladen worden, staan niet in m'n application - config file, maar in een aparte configuratie file.
Het is nl. de bedoeling dat een gebruiker zelf kan kiezen welke configuratie file er moet gebruikt worden.

https://fgheysels.github.io/


  • 6K
  • Registratie: September 2002
  • Laatst online: 19-01 15:07

6K

is ook zo...

hm... okay
en als je dan na deze keuze gewoon die config file copied naar de juiste plek en bij het einde van de sessie weer verwijderd?

want uiteindelijk wil je de gekozen config wel op een vaste plek hebben

[ Voor 22% gewijzigd door 6K op 29-09-2004 10:45 ]

٩(͡๏̯͡๏)۶ ٩(●̮̮̃•̃)۶


  • whoami
  • Registratie: December 2000
  • Laatst online: 17:54
6K schreef op 29 september 2004 @ 10:45:
hm... okay
en als je dan na deze keuze gewoon die config file copied naar de juiste plek en bij het einde van de sessie weer verwijderd?

want uiteindelijk wil je de gekozen config wel op een vaste plek hebben
Nee, dat kan ik niet doen.
Ik snap eigenlijk gewoon ook niet waarom die AppDomain.AssemblyResolve niet getriggered wordt. :?
Normaal gezien zou dit toch moeten getriggered worden? Ik krijg de fout 'file or assembly xxx or one of its dependencies not found.'.
Dat is toch een situatie waarin die event zou moeten getriggered worden? :?

https://fgheysels.github.io/


  • MTWZZ
  • Registratie: Mei 2000
  • Laatst online: 13-08-2021

MTWZZ

One life, live it!

Je kunt ook een eigen resolver toevoegen aan een AppDomain.
C#:
1
2
3
4
5
6
7
8
9
10
AppDomain currDom = AppDomain.CurrentDomain;

currDom.AssemblyResolve += new ResolveHandler(myResolver);

public AssemblyResolver myResolver(object sender, ResolveEventArgs e) {
    byte[] raw = functieDieJeAssemblyInleestAlsByteArray();
    AppDomain dom = (AppDomain)sender;
    Assembly asm = dom.Load(raw);
    return asm;
}


Dit gebruik ik om over een netwerk Assemblies te laden en het werkt vrij aardig.
Ik heb alleen nog niet helemaal uitgevonden hoe je het opgevraagde type kunt achterhalen ;-)

Nu met Land Rover Series 3 en Defender 90


  • whoami
  • Registratie: December 2000
  • Laatst online: 17:54
Wel, in m'n startpost heb ik deze event al besproken, en ik heb er ook al mee ge-experimenteerd, maar deze wordt blijkbaar niet getriggered.

https://fgheysels.github.io/


  • whoami
  • Registratie: December 2000
  • Laatst online: 17:54
MTWZZ schreef op 29 september 2004 @ 11:06:
Je kunt ook een eigen resolver toevoegen aan een AppDomain.
[code=c#]

Dit gebruik ik om over een netwerk Assemblies te laden en het werkt vrij aardig.
Ik heb alleen nog niet helemaal uitgevonden hoe je het opgevraagde type kunt achterhalen ;-)
Het type dat moet geladen worden zit wordt meegegeven in de ResolveEventARgs.
Maar goed, die event wordt dus niet getriggered bij mij. 'k Snap het niet, want normaal gezien zou dat toch moeten gebeuren.

https://fgheysels.github.io/


  • whoami
  • Registratie: December 2000
  • Laatst online: 17:54
OK.
Ik heb het uiteindelijk voor elkaar gekregen om die AssemblyResolve aan de praat te krijgen.
ipv
code:
1
Assembly.LoadFrom ()

moest ik dus
code:
1
AppDomain.CurrentDomain.LoadFrom ()

doen. :+
Echter, met AppDomain.CurrentDomain.CreateInstanceAndUnwrap ging het ook niet.... :?

https://fgheysels.github.io/


  • 6K
  • Registratie: September 2002
  • Laatst online: 19-01 15:07

6K

is ook zo...

wat vooral vreemd is, is dat hij het wel doet als de config file in de assembly dir staat. Terwijl je een hard path op geeft :X

als je dat path even in een string opvangt en je kijkt bij het debuggen, welk path geeft ie dan? (iets anders dan het harde path kun je haast niet verwachten)... en in dat geval is het inderdaad heel erg vreemd. Want nader onderzoek wijst uit dat die trigger absoluut vuurt bij het niet vinden van de assembly...

edit:
wow.. hoe ben je daar op gekomen?

[ Voor 6% gewijzigd door 6K op 29-09-2004 11:37 ]

٩(͡๏̯͡๏)۶ ٩(●̮̮̃•̃)۶


  • whoami
  • Registratie: December 2000
  • Laatst online: 17:54
6K schreef op 29 september 2004 @ 11:36:
wat vooral vreemd is, is dat hij het wel doet als de config file in de assembly dir staat. Terwijl je een hard path op geeft :X
afaik gaat de CLR in de current-directory gaan proben. Als ik die directory opvraag, dan krijg ik de directory te zien van waar ik die configuratie-file geladen heb.
Ik geef wel een absoluut path op, maar ik vermoed dat hij problemen heeft met het vinden van de referenced assemblies. Die zal hij gaan zoeken in de current-directory, terwijl die eigenlijk in dezelfde directory staan als de assembly die hij moet laden.


Echter, nu ben ik het noorden kwijt.
Er wordt aangegeven dat de assembly die ik in m'n config-file heb opgegeven niet gevonden kan worden. In de AssemblyResolve event-handler zie ik dat ResolveEventArgs.Name de naam is van de assembly die ik in m'n config file gespecifeerd heb.
Ik had hier verwacht dat het de 'referenced assembly' ging zijn van die assembly. :/

https://fgheysels.github.io/


  • whoami
  • Registratie: December 2000
  • Laatst online: 17:54
Ok.
Ik heb al m'n wijzigingen van vandaag ongedaan gemaakt, en in SourceSafe gerollbacked naar mijn laatste versie van gisteren.
Ik heb nu een kleine aanpassing daarin gedaan, en nu lijkt het perfect te werken. :P

Ik heb gewoon dit regeltje toegevoegd voor de regels waarin ik m'n assembly ga gaan loaden:
code:
1
Environment.CurrentDirectory = System.IO.Path.GetDirectory (assemblyName);

8)7

https://fgheysels.github.io/


  • 6K
  • Registratie: September 2002
  • Laatst online: 19-01 15:07

6K

is ook zo...

LOL en respect !

٩(͡๏̯͡๏)۶ ٩(●̮̮̃•̃)۶

Pagina: 1