Ich versuche herauszufinden, wie Sie eine .dll zur Laufzeit in einer C # -Anwendung importieren und verwenden können. Mit Assembly.LoadFile () habe ich es geschafft, dass mein Programm die DLL lädt (dieser Teil funktioniert definitiv, da ich mit ToString () den Namen der Klasse abrufen kann), jedoch kann ich die 'Ausgabe' nicht verwenden. Methode aus meiner Konsolenanwendung. Ich kompiliere die .dll und verschiebe sie dann in das Projekt meiner Konsole. Gibt es einen zusätzlichen Schritt zwischen CreateInstance und anschließendem Verwenden der Methoden?
Dies ist die Klasse in meiner DLL:
namespace DLL
{
using System;
public class Class1
{
public void Output(string s)
{
Console.WriteLine(s);
}
}
}
und hier ist die Anwendung, die ich die DLL laden möchte
namespace ConsoleApplication1
{
using System;
using System.Reflection;
class Program
{
static void Main(string[] args)
{
var DLL = Assembly.LoadFile(@"C:\visual studio 2012\Projects\ConsoleApplication1\ConsoleApplication1\DLL.dll");
foreach(Type type in DLL.GetExportedTypes())
{
var c = Activator.CreateInstance(type);
c.Output(@"Hello");
}
Console.ReadLine();
}
}
}
Mitglieder müssen zur Kompilierzeit auflösbar sein, um direkt von C # aufgerufen zu werden. Ansonsten müssen Sie Reflexions- oder dynamische Objekte verwenden.
Reflexion
namespace ConsoleApplication1
{
using System;
using System.Reflection;
class Program
{
static void Main(string[] args)
{
var DLL = Assembly.LoadFile(@"C:\visual studio 2012\Projects\ConsoleApplication1\ConsoleApplication1\DLL.dll");
foreach(Type type in DLL.GetExportedTypes())
{
var c = Activator.CreateInstance(type);
type.InvokeMember("Output", BindingFlags.InvokeMethod, null, c, new object[] {@"Hello"});
}
Console.ReadLine();
}
}
}
Dynamisch (.NET 4.0)
namespace ConsoleApplication1
{
using System;
using System.Reflection;
class Program
{
static void Main(string[] args)
{
var DLL = Assembly.LoadFile(@"C:\visual studio 2012\Projects\ConsoleApplication1\ConsoleApplication1\DLL.dll");
foreach(Type type in DLL.GetExportedTypes())
{
dynamic c = Activator.CreateInstance(type);
c.Output(@"Hello");
}
Console.ReadLine();
}
}
}
Im Moment erstellen Sie eine Instanz von jedem Typ, der in der Assembly definiert ist. Sie müssen nur eine einzige Instanz von Class1
erstellen, um die Methode aufzurufen:
class Program
{
static void Main(string[] args)
{
var DLL = Assembly.LoadFile(@"C:\visual studio 2012\Projects\ConsoleApplication1\ConsoleApplication1\DLL.dll");
var theType = DLL.GetType("DLL.Class1");
var c = Activator.CreateInstance(theType);
var method = theType.GetMethod("Output");
method.Invoke(c, new object[]{@"Hello"});
Console.ReadLine();
}
}
Sie müssen eine Instanz des Typs erstellen, die die Output
-Methode verfügbar macht:
static void Main(string[] args)
{
var DLL = Assembly.LoadFile(@"C:\visual studio 2012\Projects\ConsoleApplication1\ConsoleApplication1\DLL.dll");
var class1Type = DLL.GetType("DLL.Class1");
//Now you can use reflection or dynamic to call the method. I will show you the dynamic way
dynamic c = Activator.CreateInstance(class1Type);
c.Output(@"Hello");
Console.ReadLine();
}
Ich habe 3 Schleifen, an denen ich die dynamische Referenz der Klasse in Schleifen übergeben möchte
privates Objekt extractSeatLayout (dynamisches colA) {
//Type type1 = Assembly.GetType("Bigtree.VistaRemote.objArea");
//dynamic objArea = Activator.CreateInstance(type1, null);
//Type type2 = Assembly.GetType("Bigtree.VistaRemote.objRow");
//dynamic objR = Activator.CreateInstance(type2, null);
//Type type3 = Assembly.GetType("Bigtree.VistaRemote.objSeat");
//dynamic objS = Activator.CreateInstance(type3, null);
Dictionary<string, object> collectionArea = new Dictionary<string, object>();
//collectionArea.Add("Count", colA.Count);
//collectionArea.Add("intMaxSeatId", colA.intMaxSeatId());
//collectionArea.Add("intMinSeatId", colA.intMinSeatId());
try
{
collectionArea.Add("Count", colA.GetType().GetProperty("Count").GetValue(colA, null));
collectionArea.Add("intMaxSeatId", colA.GetType().GetMethod("intMaxSeatId").Invoke(colA, null));
collectionArea.Add("intMinSeatId", colA.GetType().GetMethod("intMinSeatId").Invoke(colA, null));
}
catch (Exception ex)
{
throw ex;
}
List<Dictionary<string, object>> arrayArea = new List<Dictionary<string, object>>();
foreach (dynamic objA in colA)
{
Dictionary<string, object> area = new Dictionary<string, object>();
////area.Add("AreaDesc", objA.strAreaDesc);
// //area.Add("AreaCode", objA.strAreaCode);
// //area.Add("AreaNum", objA.strAreaNum);
// //area.Add("HasCurrentOrder", objA.blnHasCurrentOrder());
area.Add("AreaDesc", objA.GetType().GetProperty("strAreaDesc").GetValue(objA, null));
area.Add("AreaCode", objA.GetType().GetProperty("strAreaCode").GetValue(objA, null));
area.Add("AreaNum", objA.GetType().GetProperty("strAreaNum").GetValue(objA, null));
area.Add("HasCurrentOrder", objA.GetType().GetMethod("blnHasCurrentOrder").Invoke(objA, null));
List<Dictionary<string, object>> arrayRow = new List<Dictionary<string, object>>();
foreach (dynamic objR in objA)
{
Dictionary<string, object> row = new Dictionary<string, object>();
//row.Add("GridRowId", objR.intGridRowID);
//row.Add("PhyRowId", objR.strRowPhyID);
row.Add("GridRowId", type.GetProperty("intGridRowID").GetValue(objR, null));
row.Add("PhyRowId", type.GetProperty("strRowPhyID").GetValue(objR, null));
List<Dictionary<string, object>> arraySeat = new List<Dictionary<string, object>>();
var rowCount = 0;
foreach (dynamic objS in objR)
{
Dictionary<string, object> seat = new Dictionary<string, object>();
//seat.Add("GridSeatNum", objS.intGridSeatNum);
//seat.Add("SeatStatus", objS.strSeatStatus);
//seat.Add("Xpos", objS.dblSeatXPos);
//seat.Add("StrSeatNumber", objS.strSeatNumber);
//seat.Add("seatNumber", ++rowCount);
//seat.Add("type", objS.strGroupSeatType);
seat.Add("GridSeatNum", type.GetProperty("intGridSeatNum").GetValue(objS, null));
seat.Add("SeatStatus", type.GetProperty("strSeatStatus").GetValue(objS, null));
seat.Add("Xpos", type.GetProperty("dblSeatXPos").GetValue(objS, null));
seat.Add("StrSeatNumber", type.GetProperty("strSeatNumber").GetValue(objS, null));
seat.Add("seatNumber", ++rowCount);
seat.Add("type", type.GetProperty("strGroupSeatType").GetValue(objS, null));
arraySeat.Add(seat);
}
row.Add("objSeat", arraySeat);
arrayRow.Add(row);
}
area.Add("objRow", arrayRow);
arrayArea.Add(area);
}
collectionArea.Add("objArea", arrayArea);
return collectionArea;
}
Activator.CreateInstance()
gibt ein Objekt zurück, das keine Ausgabemethode hat.
Wie es aussieht, kommen Sie aus dynamischen Programmiersprachen? C # ist definitiv nicht das, und was Sie zu tun versuchen, wird schwierig sein.
Da Sie eine bestimmte DLL von einem bestimmten Speicherort laden, möchten Sie sie möglicherweise nur als Referenz zu Ihrer Konsolenanwendung hinzufügen.
Wenn Sie die Assembly unbedingt über Assembly.Load
laden möchten, müssen Sie über Reflection alle Mitglieder über c
aufrufen.
Etwas wie type.GetMethod("Output").Invoke(c, null);
sollte es tun.