Also,
zur Laufzeit erstelle ich ein cs file, welches eine simple klasse
enthält:
1
usingSystem;
2
namespaceWindowsFormsApplication1
3
{
4
classbla
5
{
6
publicintxyz;
7
publicbla(){}
8
publisvoidsetbla(intval){xyz=val;}
9
}
10
}
Ich muss nun auf diese Klasse zugreifen können. Also kompiliere ich
diese und erstelle eine DLL. Das sollte doch prinzipiell machbar sein,
mit der obigen Klasse oder?
Dazu habe ich dieses Beispiel verwendet und anstatt einer EXE, eine DLL
daraus gemacht http:
http://msdn.microsoft.com/en-us/library/system.codedom.compiler.compilerparameters.generateexecutable.aspx
Hat auch soweit geklappt.
Wie binde ich diese nun zur Laufzeit ein? Muss ich dazu eine neue Domäne
anlegen? Weil wenn ich mir das so anschaue, verstehe ich nur Bahnhof!
Kann mir jemand weiterhelfen?
Das ist so eine Sache. Rufe zur Laufzeit eine exe auf, die ein file
parst und daraus eben diese Klasse erstellt. Wüsste nicht wie ich es
anders lösen könnte. Aber den c code, aus dem die exe erstellt wurde, zu
portieren, würde etwas länger dauern, deswegen dieser weg.
ok werde es mal testen.
Peterle Anonym schrieb:> Muss ich dazu eine neue Domäne> anlegen?
nur wenn du das assembly wieder entladen möchtest, es gibt (zumindest
bis .net35) keinen mechanismus ein einmal geladenes assemlby wieder zu
entladen. das zerstören einer appdomain ginge aber.
Hi Peterle,
.net hat ein mächtiges Feature: Reflection. Es bietet die Lösung für
dein(e) Problem(e). Du müßtest Dir zunächst eine Instanz des Compilers
über System.CodeDOM.CodeDOMProvider.CreateCompiler("CSharp") und über
deren Methode CompileSourceFromFile (...FromSource,...FromDOM) ein
Assembly-Objekt erzeugen. Über Reflection kannst Du dann Objekte von
Klassen aus Deiner Assembly instanziieren und Methoden derselben
aufrufen.
Eine andere Möglichkeit wäre, die Methoden der Objekte aus der zur
Laufzeit erzeugten Assembly über ein Interface anzusprechen, das
natürlich zur Compile-Zeit Deines Hauptprogramms vorhanden sein muß.
Dann sparst Du Dir den Methodenaufruf über Reflection.
Du solltest auf jeden Fall mal die MSDN-Doku zum Thema konsultieren, da
es leider einige Parameter bei den beteiligten Klassen gibt, die passend
versorgt sein wollen.
Gruß
Markus
Christian R. schrieb:> Wenn du das Assembly als DLL vorliegen hast, kannst mit Reflection alles> damit tun!> var assembly = System.Reflection.Assembly.LoadFrom(@"c:\assembly.dll");>> aus dem assembly ladest du die Typendefinitionen:> var type = assembly.GetType("Klassenname");>> und mit Activator kannst du dann eine Instanz der Klasse erzeugen> object instance = Activator.CreateInstance(type);>>> Warum aber überhaupt on the fly assemblies erzeugen??? ? ?? ... ?>> Grüße,> Christian
Wie greife ich dann auf die Methode der klasse zu, denn zur
Kompilierzeit ist diese nicht bekannt und der Compiler meckert:
Markus Volz schrieb:> Hi Peterle,>> .net hat ein mächtiges Feature: Reflection. Es bietet die Lösung für> dein(e) Problem(e). Du müßtest Dir zunächst eine Instanz des Compilers> über System.CodeDOM.CodeDOMProvider.CreateCompiler("CSharp") und über> deren Methode CompileSourceFromFile (...FromSource,...FromDOM) ein> Assembly-Objekt erzeugen. Über Reflection kannst Du dann Objekte von> Klassen aus Deiner Assembly instanziieren und Methoden derselben> aufrufen.>> Eine andere Möglichkeit wäre, die Methoden der Objekte aus der zur> Laufzeit erzeugten Assembly über ein Interface anzusprechen, das> natürlich zur Compile-Zeit Deines Hauptprogramms vorhanden sein muß.> Dann sparst Du Dir den Methodenaufruf über Reflection.>> Du solltest auf jeden Fall mal die MSDN-Doku zum Thema konsultieren, da> es leider einige Parameter bei den beteiligten Klassen gibt, die passend> versorgt sein wollen.>> Gruß> Markus
hi,
ja also kompiliert habe ich das ganze zur laufzeit schon und eine dll
wurde auch erstellt. das hab ich folgendermaßen gemacht:
>> aus dem assembly ladest du die Typendefinitionen:>>
1
>vartype=assembly.GetType("Klassenname");
2
>
wenn ich hier den klassennamen reinschreibe, liefert mir GetType null
zurück
und:
> und mit Activator kannst du dann eine Instanz der Klasse erzeugen>>
1
>objectinstance=Activator.CreateInstance(type);
2
>
das schlägt fehl.
Ohne Parameter liefert GetType schon mal nicht null, sondern
System.Reflection.RuntimeAssembly. Dann aber sagt er
No parameterless constructor defined for this object
stimmt vll was mit meiner DLL nicht, bzw der darin enthaltenen klasse?
Wenn ich mir GetType(string)-Methode anschaue, steht in der msdn, dass
dieser ein AssemblyQualifiedName erwartet... oh man
Na ja, Du musst beim Klassenname zumindest mal den Namespace mit
angeben, sonst wird das nichts, gemäß Deinem obigen Beispiel:
WindowsFormsApplication1.bla.
Wieso versuchst Du eigentlich, die Assembly als Datei von der Platte zu
laden? Das geht natürlich, aber Du hast sie im CompilerResult-Objekt
bereits als Objekt vorliegen und kannst direkt damit arbeiten. Zum
Compilieren musst Du den Sourcecode auch nicht in eine Datei schreiben.
Du kannst auch ein String-Objekt compilieren.
Aus Deinen Infos oben geht nicht so klar hervor, ob die DLL nun eine
Windows-DLL oder eine .net-Assembly ist. Die haben zwar beide die selbe
Dateinamenserweiterung (.dll), haben aber sonst nichts gemeinsam.
Eine Windows-DLL kannst Du mittels P-Invoke laden und Funktionen daraus
ansprechen. Für .net-Assemblies ist Reflection vorgesehen.
Gruß
Markus
wie hier beschrieben:
Beitrag "Re: C# Zur Laufzeit Modul kompilieren und darauf zugreifen"
handelt es sich um ein assembly.
>aber Du hast sie im CompilerResult-Objekt>bereits als Objekt vorliegen und kannst direkt damit arbeiten
meinst du ich kann direkt mit dieser Referenz arbeiten:
>Compilieren musst Du den Sourcecode auch nicht in eine Datei schreiben.>Du kannst auch ein String-Objekt compilieren.
naja die zu kompilierende Datei wird ja durch ein externes Programm zur
Laufzeit erzeugt. wüsste nicht wie ich da einen string übergeben
könnte?!
Ok, da der Sourcecode extern erzeugt wird, ist CompileAssemblyFromFile
natürlich die bessere Wahl.
Die Objekte des Typs CompilerResults haben ein Property CompiledAssembly
vom Typ Assembly. Von diesem Assembly-Objekt kannst Du dann wieder die
Methode CreateInstance aufrufen, um Instanzen von Deiner Klasse zu
erhalten. Der Klassenname umfasst, wie bereits oben erwähnt, neben dem
Klassennamen natürlich auch den Namespace!
Gruß
Markus
Markus Volz schrieb:> Ok, da der Sourcecode extern erzeugt wird, ist CompileAssemblyFromFile> natürlich die bessere Wahl.>> Die Objekte des Typs CompilerResults haben ein Property CompiledAssembly> vom Typ Assembly. Von diesem Assembly-Objekt kannst Du dann wieder die> Methode CreateInstance aufrufen, um Instanzen von Deiner Klasse zu> erhalten. Der Klassenname umfasst, wie bereits oben erwähnt, neben dem> Klassennamen natürlich auch den Namespace!>> Gruß> Markus
ahh, cool, mit dem namespace klappt es, wie trivial...
Aber wenn ich jetzt einen member (methode, variable) aufrufen will,
meckert er, da er sie ja zur compile-zeit nicht kennt!!
Peterle Anonym schrieb:> ahhh danke, klappt soweit.>> Kann es sein, dass ich für jede methode die ich aufrufen will eine neues> instance erzeugen muss via CreateInstance?
1) Nein wie kommst du darauf?
2) Wie wäre es eigentlich dem Rat mal zu folgen sich in das Themengebiet
einzulesen? Alternativ bitte den vollständigen Code liefern das wir dir
das hier jetzt nicht Stück für Stück zusammenprogrammieren müssen...