Die Parametrierung DllImport für die Verwendung in einer C# - Anwendung
Wir haben einen Anbieter, der bietet eine Bibliothek für den Zugriff auf Ihre hardware. Leider, wenn Sie mehrere Geräte besitzen, müssen Sie es importieren, Ihre Bibliothek mehrere Male, mit verschiedenen dll-Namen. Als Konsequenz haben wir eine Tonne von duplizierten code, und ich bin besorgt, dass es bald ein Wartungs-Albtraum.
Was wir im moment haben, ist so etwas wie:
namespace MyNamespace {
public static class Device01 {
public const string DLL_NAME = @"Device01.dll";
[DllImport(DLL_NAME, EntryPoint = "_function1")]
public static extern int Function1(byte[] param);
...
[DllImport(DLL_NAME, EntryPoint = "_function99")]
public static extern int Function99(int param);
}
....
public static class Device16 {
public const string DLL_NAME = @"Device16.dll";
[DllImport(DLL_NAME, EntryPoint = "_function1")]
public static extern int Function1(byte[] param);
...
[DllImport(DLL_NAME, EntryPoint = "_function99")]
public static extern int Function99(int param);
}
}
Wenn ich mit C oder C++, würde ich einfach definieren die Funktionen einer Datei #include Sie mehrmals in den statischen Klassen, nicht schön aber besser als die alternative, aber in C# habe ich nicht, die option.
Wenn jemand irgendwelche kluge Ideen über, wie man effektiv definieren eine Fabrik, die es uns erlauben würde, um so viele statische device-Klassen, wie wir brauchen, wäre ich sehr daran interessiert.
Dank,
Edit: Die Funktionsprototypen sind ganz videly abwechslungsreich, so dass jede Methode, die auf Ihnen beruht, der gleiche wäre nicht geeignet. Vielen Dank für die Anregungen bisher, ich war nicht expacting so viele Ideen, ganz so schnell.
- Zu deinem letzten edit: meine "Dritte Ansatz" kann angepasst werden, um alles, was Sie mögen. Erstellen Sie einen Delegaten-Typ für jede Methode (müssen Sie sowieso, und Sie haben, dass derzeit bereits als
DllImport
s), fügen Sie ein param-array für Parameter und Generika verwendet, um die Aufrufe von typesafe. Halten Sie auf, ich werde versuchen, passen Sie die Beispiel. - Mit dem Zusatz "Delegierte Reflexion" (tx Eric Lippert) und Generika, es behebt Ihr Problem, für fast jede Art von P/Invoke-Aufrufe, die Sie antreffen können 😉
Du musst angemeldet sein, um einen Kommentar abzugeben.
Nur einige überlegungen:
Alternative #one
EDIT: dieser Ansatz erfordert die änderung kompiliert Methoden, das ist schwer und erfordert Spritzguss, assembly, änderung oder andere Methoden, die Häufig verwendet werden in der AOP-land. Betrachten Ansatz zwei unten, das ist einfacher.
GetIlAsByteArray
zum erstellen einer dynamischen Methode IhrerDllImport
MethodeAlternative #zwei:
EDIT: Diese alternative Methode scheint ein bisschen beteiligt an den ersten, aber jemand hat bereits die Arbeit für Sie. Nachschlagen diese ausgezeichnete CodeProject Artikel und einfach herunterladen und verwenden den code, um dynamisch erstellen DllImport-style-Methoden. Grundsätzlich kommt es zu:
LoadLibrary
oderLoadLibraryEx
mit dem dllimport-API-FunktionenMethodBuilder
.Alternative #drei
EDIT: Suche weiter, es ist ein einfacher Ansatz: einfach zu verwenden
DefinePInvokeMethod
die Sie brauchen. Der MSDN-link gibt bereits ein gutes Beispiel, aber ein full-wrapper erstellen kann, eine Native DLL, basierend auf DLL und Funktion-name ist in dieser CodeProject Artikel.DefinePInvokeMethod
Ist hier, wie dieser Ansatz sieht im code, die Sie wiederverwenden können zurückgegeben delegieren Sie so viel Sie möchten, die kostspielige Bau der dynamischen Methode sollte nur durchgeführt werden, einmal pro Methode.
EDIT: aktualisiert code-Beispiel funktioniert mit jeder Delegierte und automatisch entsprechend den richtigen Rückgabetyp und Parametertypen des Delegaten Signatur. Auf diese Weise, wir entkoppelten die Umsetzung vollständig aus der Signatur, das ist, angesichts Ihrer derzeitigen situation, das beste was wir tun können. Vorteile: Sie geben Sicherheit und single-point-of-change, das bedeutet: sehr gut überschaubar.
Andere Ansätze sind möglich, denke ich (wie die Template-Ansatz erwähnt, den jemand anderes in diesem thread).
Update: noch einen link zu ausgezeichnete codeproject Artikel.
Update: Dritten und einfacher Ansatz Hinzugefügt.
Update: Hinzugefügt Beispielcode
Update: aktualisiert code-Beispiel funktioniert nahtlos mit jeder Funktion Prototyp
Update: Feste schrecklichen Fehler:
typeof(Function02)
solltetypeof(T)
natürlichMethodBuilder
Klasse zu erstellen, die Sie zur Laufzeit, aber Sie haben Recht, dass Sie nicht ändern können Sie für kompilierte Methoden (es sei denn, Sie verwenden eine der vielen ausgezeichneten Injektion / AOP-Bibliotheken).Wie über die Verwendung T4 (Text Template Transformation Toolkit). Erstellen Sie eine .tt-Datei mit dem folgenden Inhalt:
Visual Studio wird dann konvertieren Sie diese in:
Ich würde auch nur empfehlen, bei Verwendung der systemeigenen
LoadLibrary
undGetProcAddress
.Mit der letzteren, rufen Sie einfach
Marshal.GetDelegateForFunctionPointer
mit einem Delegaten-Typ, entspricht der pinvoke-Signatur der Methode.GetDelegateForFunctionPointer
ich konnte ihn nicht finden, als ich ging, über meine erste Lösung. Es werde schwer sein, um die drei api-Aufrufe arbeiten mit Variablen Parametern und Rückgabetypen für die Prototypen-und behalten trotzdem die Typsicherheit.