Beispiel für ein Konsolenprogramm.
class Program
{
static void Main(string[] args)
{
// ... code to build dll ... not written yet ...
Assembly assembly = Assembly.LoadFile(@"C:\dyn.dll");
// don't know what or how to cast here
// looking for a better way to do next 3 lines
IRunnable r = assembly.CreateInstance("TestRunner");
if (r == null) throw new Exception("broke");
r.Run();
}
}
Ich möchte dynamisch eine Assembly (.dll) erstellen und dann die Assembly laden, eine Klasse instanziieren und die Run () -Methode dieser Klasse aufrufen. Sollte ich versuchen, die TestRunner-Klasse auf etwas zu übertragen? Ich bin mir nicht sicher, wie die Typen in einer Assembly (dynamischer Code) über meine Typen in meiner (statische Assembly / Shell-App) Bescheid wissen würden. Ist es besser, nur ein paar Zeilen Reflektionscode zu verwenden, um Run () nur für ein Objekt aufzurufen? Wie sollte dieser Code aussehen?
UPDATE: William Edmondson - siehe Kommentar
c#
.net
reflection
BuddyJoe
quelle
quelle
export
undimport
Klassen in separaten Baugruppen von einer bekannten Schnittstelle ableitenAntworten:
Verwenden Sie eine AppDomain
Es ist sicherer und flexibler, die Baugruppe selbst zu laden
AppDomain
.Also anstelle der zuvor gegebenen Antwort :
Ich würde Folgendes vorschlagen (angepasst aus dieser Antwort auf eine verwandte Frage ):
Jetzt können Sie die Baugruppe entladen und verschiedene Sicherheitseinstellungen vornehmen.
Wenn Sie noch mehr Flexibilität und Leistung für das dynamische Laden und Entladen von Assemblys wünschen, sollten Sie sich das Managed Add-Ins Framework (dh den
System.AddIn
Namespace) ansehen . Weitere Informationen finden Sie in diesem Artikel zu Add-Ins und Erweiterbarkeit auf MSDN .quelle
CreateInstanceFromAndUnwrap
erfordert den AssemblyName eher als einen Pfad; meinst duCreateFrom(path, fullname).Unwrap()
? Auch ich wurde von derMarshalByRefObject
AnforderungCreateInstanceAndUnwrap(typeof(TypeIWantToLoad).Assembly.FullName, typeof(TypeIWantToLoad).FullName)
?Wenn Sie keinen Zugriff auf die
TestRunner
Typinformationen in der aufrufenden Assembly haben (dies scheint nicht der Fall zu sein), können Sie die Methode folgendermaßen aufrufen:Wenn Sie Zugriff auf den
IRunnable
Schnittstellentyp haben, können Sie Ihre Instanz in diesen umwandeln (und nicht in denTestRunner
Typ, der in der dynamisch erstellten oder geladenen Assembly implementiert ist, oder?):quelle
Ich mache genau das, wonach Sie in meiner Regel-Engine suchen, die verwendet CS-Script zum dynamischen Kompilieren, Laden und Ausführen von C # verwendet. Es sollte leicht in das zu übersetzen sein, wonach Sie suchen, und ich werde ein Beispiel geben. Zuerst der Code (abgespeckte):
Dies nimmt eine Schnittstelle vom Typ T, kompiliert eine CS-Datei in eine Assembly, instanziiert eine Klasse eines bestimmten Typs und richtet diese instanziierte Klasse an der T-Schnittstelle aus. Grundsätzlich müssen Sie nur sicherstellen, dass die instanziierte Klasse diese Schnittstelle implementiert. Ich benutze Eigenschaften, um alles einzurichten und darauf zuzugreifen, wie folgt:
In Ihrem Beispiel möchten Sie Run () aufrufen, daher würde ich eine Schnittstelle erstellen, die die Run () -Methode wie folgt definiert:
Erstellen Sie dann eine Klasse, die sie wie folgt implementiert:
Ändern Sie den Namen von RulesEngine in TestHarness und legen Sie Ihre Eigenschaften fest:
Dann können Sie überall dort, wo Sie es aufrufen möchten, einfach Folgendes ausführen:
Es würde wahrscheinlich gut für ein Plugin-System funktionieren, aber mein Code ist so wie er ist auf das Laden und Ausführen einer Datei beschränkt, da sich alle unsere Regeln in einer C # -Quelldatei befinden. Ich würde denken, dass es ziemlich einfach wäre, es so zu ändern, dass nur die Typ- / Quelldatei für jede Datei übergeben wird, die Sie ausführen möchten. Sie müssten nur den Code aus dem Getter in eine Methode verschieben, die diese beiden Parameter verwendet.
Verwenden Sie Ihr IRunnable auch anstelle von ITestRunner.
quelle
Sie müssen Reflection verwenden, um den Typ "TestRunner" zu erhalten. Verwenden Sie die Assembly.GetType-Methode.
quelle
MethodInfo
Typ und Anruf erhaltenInvoke
? (Ich verstand die ursprüngliche Frage als Angabe des Anrufers, der nichts über den fraglichen Typ wusste.)Wenn Sie Ihre Assembly erstellen, können Sie sie aufrufen
AssemblyBuilder.SetEntryPoint
und dann von derAssembly.EntryPoint
Eigenschaft zurückholen , um sie aufzurufen.Denken Sie daran, dass Sie diese Signatur verwenden möchten, und beachten Sie, dass sie nicht benannt werden muss
Main
:quelle