Reflections - wie richtig nutzen ?
-
Habe lange nach einer Möglichkeit gesucht ein kleines PlugIn System für mein Übungsprojekt "Sidebar" zu verwirklichen. Nach langem suchen bin ich auf die Reflections gestoßen. Wobei ich aber nicht sicher bin ob dies die beste Lösung für mich ist. Na ja, hab einfach mal angefangen:
Es geht darum, dass die einzelnen Panel der Sidebar zur Laufzeit geladen werden. Ein PlugIn System eben.
Zum Testen habe ich eine einfache Form DLL erstellt und versuche sie wie folgt zu laden:
//PlugIns aus dem Verzeichniss holen array<System::String^>^ dateien = System::IO::Directory::GetFiles (arbeitsordnerholen () + "PlugIns\\","*.dll"); //... und laden for each (String^ datei in dateien) { try { //Assembly Laden System::Reflection::Assembly ^exAss = ::Reflection::Assembly::LoadFrom (datei); //Modul besorgen System::Reflection::Module ^AssMod = exAss->GetModule ( datei->Substring (datei->LastIndexOf ("\\") + 1) ); //Array von verfügbaren Modulen holen array<Type^,1>^ typen = AssMod->GetTypes (); String^ classname = typen[0]->AssemblyQualifiedName->Substring (0, typen[0]->AssemblyQualifiedName->IndexOf (",")); //Typ des Modules finden System::Type ^exForm = AssMod->GetType (classname); //u Form casten Form ^inForm = safe_cast<Form^>(Activator::CreateInstance(exForm)); //in Liste eintragen plugins.Add (exAss); } catch (Exception^) { continue; }
Nun lasst es Kritik regnen. Ich bin lernwillig.
1.)Es stellt sich mir nun die Frage, wie ich denn an die Member Funktionen meiner Panel PlugIns komme - wovon InitializePanel () in jedem PlugIn Vorhanden ist. Hier soll dann bspw. die zukünftige Position des Panels übergeben werden.
2.)Auch gefällt mir das zusammenbasteln der Modulnamen irgendwie nicht. Wie löst man das besser?
3.)Gehen wir davon aus, dass ich die einzelnen Panels von einer Basisklasse ableiten möchte - welche nicht als PlugIn vorliegt, sondern im Hauptquelltext der Sidebar selber. Wie gehe ich hier vor?
Greetz
-
Psydocode: (Suchmethode)
List<PlugInPanel>^ result = gcnew List<PlugInPanel>(); for each(String^ fileName in System::IO::Directory::GetFiles (arbeitsordnerholen () + "PlugIns\\","*.dll")) { // hier eine Fehlerbehebung für Fehler von LoadFrom System::Reflection::Assembly ^exAss = ::Reflection::Assembly::LoadFrom (datei); for each(Type^ t in exAss->GetTypes()) if(t->IsPublic && t->IsSubClassOf(typepf(PlugInPanel) ) // Fehler von CreateInstance result->Add(safe_cast<Form^>(Activator::CreateInstance(t))); // vielleicht noch auf CreateInstance == null überprüfen } } return result;
Psydocode: (Addmethode)
for each(PlugInPanel^ p in Suchmethode()) richtigesPanel->Controls->Add(p);
Psydocode == Ausm Kopf - ohne Überprüfung
Außerdem sollte man noch pro Plugin eine AppDomain erstellen mit geringeren Rechten, damit diese auch einzeln entladen werden können.
-
shaun1981 schrieb:
Habe lange nach einer Möglichkeit gesucht ein kleines PlugIn System für mein Übungsprojekt "Sidebar" zu verwirklichen.
irgendwie bin ich der Meinung das ich Dir den Link schon mal gegeben hatte - Calculon - All My Plugins - vieleicht aber auch nicht
1.)Es stellt sich mir nun die Frage, wie ich denn an die Member Funktionen meiner Panel PlugIns komme - wovon InitializePanel () in jedem PlugIn Vorhanden ist. Hier soll dann bspw. die zukünftige Position des Panels übergeben werden.
die einzelnen Plugins sollte schon ein Interface (oder abstrakte Klasse) implementieren das alle beteiligten Seiten kennen ... dann kannst Du das Objekt daruf casten undauf die Methoden etc. zugreifen
2.)Auch gefällt mir das zusammenbasteln der Modulnamen irgendwie nicht. Wie löst man das besser?
jedes Plugin in einen eigenen Ordner und der hat eine Konfigurationsdatei, wo die nötigen Daten drinnen stehen
3.)Gehen wir davon aus, dass ich die einzelnen Panels von einer Basisklasse ableiten möchte - welche nicht als PlugIn vorliegt, sondern im Hauptquelltext der Sidebar selber. Wie gehe ich hier vor?
das was Du machen kannst, willst Du nicht wirklich machen ... einen Verweis auf das Projekt (welches die Basisklasse enthält) hinzufügen ... lager die Basisklasse besser in eine extra DLLaus füge diese DLL überall (wo die Klasse benötigt wird) als Verweis hinzu
hand, mogel
-
Wie erwartet habe ich hier noch Schwierigkeiten:
Was ich einfach nicht verstehe: Wie baue ich die Interface Klasse auf - was kommt hinein ?
1.) Meiner Sidebar Hauptform (Form1) habe ich einen Verweis auf die Interface.dll zugewiesen - und ist bekannt.
2.) Dann habe ich eine zweite Form in einer neuen Projekt Mappe (PlugIn) mit dem Namen "Slideshowpanel". Auch hier ist die Interface Klasse gelinkt und bekannt.
Wie kann ich nun über das Interface auf die PlugIns zugreifen?
-
shaun1981 schrieb:
Was ich einfach nicht verstehe: Wie baue ich die Interface Klasse auf - was kommt hinein ?
genau das was Du benötigst um vom Hauptprogramm aus mit dem Plugin kommunizieren zu können ... wenn im Tutorial noch double verarbeitet werden sollen, dann muss im Interface eine entsprechende Methode hin ... was da rein muss, das kannst nur Du wissen - nur Du weist was Dein Programm/Plugin machen soll
1.) Meiner Sidebar Hauptform (Form1) habe ich einen Verweis auf die Interface.dll zugewiesen - und ist bekannt.
2.) Dann habe ich eine zweite Form in einer neuen Projekt Mappe (PlugIn) mit dem Namen "Slideshowpanel". Auch hier ist die Interface Klasse gelinkt und bekannt.
Wie kann ich nun über das Interface auf die PlugIns zugreifen?
auf das Plugin kannst Du nicht direkt darauf zugreifen - nur über Interfaces ... das Hauptprogramm weis (über das Interface) "das kann dieses Plugin alles" ... das Plugin weis (über das Interface) "das will das Hauptprogramm alles von mir wissen"
was das Plugin macht ist unabhängig von dem was das Hauptprogramm will ... folgendes Beispiel hat nicht mehr viel mit Berechnung unter Calculon gemeinsam
Public Class Operation Implements Calculon.CalculonPlugin Public Function Calculate(ByVal valueA As Integer, ByVal valueB As Integer) _ As Integer Implements Calculon.CalculonPlugin.Calculate Dim f as new Form() f->ShowDialog(); Return 0 End Function Public Overrides Function ToString() As String Return "1337-H4CK" End Function End Class
hand, mogel
-
Habe echt arge Probleme dies umzusetzen. Den Sinn des Interfaces habe ich aber verstanden. Hier mal ein wenig Code:
protected: static System::Collections::Generic::List<Form^> plugins = gcnew System::Collections::Generic::List<Form^>();
Interface
// Interface.h #pragma once using namespace System; namespace Interface { public interface class PlugInInterface { bool check (void); void InitializePanel (void); }; }
Form1.h
namespace Sidebar { public ref class Form1 : public System::Windows::Forms::Form , Interface::PlugInInterface { protected: static System::Collections::Generic::List<Form^> plugins = gcnew System::Collections::Generic::List<Form^>(); public: static int auflösungx = GetSystemMetrics(SM_CXSCREEN), auflösungy = GetSystemMetrics(SM_CYSCREEN); public: static int movemodus = 0, panelanzahl = 0; protected: static int FXintro = 0; public: static Point pos; protected: System::Media::SoundPlayer^ player; public: void panelsladen (void); public: String^ arbeitsordnerholen (); public: void bildschirmauflösung (); public: void fensterminimieren (); public: void sichtbarkeit (int); public: void beenden (); public: void workareastandard (); public: void sidebarandocken (); public: void position (); public: void formabrunden (int, int, int, int, int); public: void panelseinlesen (); public: void formaktualisieren (); //Interface Implementierung virtual bool check (void); virtual void InitializePanel (void); public: Form1(void) { InitializeComponent(); workareastandard (); ... ...
Form1.cpp
bool Sidebar::Form1::check (void) { return true; } void Sidebar::Form1::InitializePanel (void) { } ... ...
Slideshowpanel.h
public ref class Slideshowpanel : public System::Windows::Forms::Form { public: Slideshowpanel(void) { InitializeComponent(); } protected: /// <summary> /// Verwendete Ressourcen bereinigen. /// </summary> ~Slideshowpanel() { if (components) { delete components; } } public: void InitializePanel (void); public: bool check (void); private: System::Windows::Forms::Label^ label1; protected: ... ...
Slideshowpanel.cpp
#include "Slideshowpanel.h" void PlugIns::Slideshowpanel::InitializePanel (void) { } bool PlugIns::Slideshowpanel::check (void) { return true; } ...
Wo liegt mein Denkfehler?
-
shaun1981 schrieb:
Habe echt arge Probleme dies umzusetzen. Den Sinn des Interfaces habe ich aber verstanden. Hier mal ein wenig Code:
Dein Sidebar muss das Interface nicht implmentieren - es muss es nur kennen ... implementieren müssen das nur Deine Plugins ... dann ein paar Vorschläge
public interface class PlugInInterface { bool check (void); void InitializePanel (void); UserControl ^getPanel(); // liefert das UserControl das in das Sidebar soll };
static System::Collections::Generic::List<Form^> plugins = gcnew System::Collections::Generic::List<Form^>(); // würde ich lieber die Plugins sammeln static System::Collections::Generic::List<PlugInInterface^> plugins = gcnew System::Collections::Generic::List<PlugInInterface^>();
wenn Du die Plugins aus den Assembly geladen hast kannst Du einfach über die Liste itereieren und mit getPreview das UserControl holen und dem Sidebar hinzufügen
ich hoffe Dir weiter geholfen zu haben, mogel
-
3.)Gehen wir davon aus, dass ich die einzelnen Panels von einer Basisklasse ableiten möchte - welche nicht als PlugIn vorliegt, sondern im Hauptquelltext der Sidebar selber. Wie gehe ich hier vor?
das was Du machen kannst, willst Du nicht wirklich machen ... einen Verweis auf das Projekt (welches die Basisklasse enthält) hinzufügen ... lager die Basisklasse besser in eine extra DLLaus füge diese DLL überall (wo die Klasse benötigt wird) als Verweis hinzu
Hierzu habe ich nochmal eine Frage. Habe versucht meine Basis Klasse in eine DLL auszulagern - was auch augenscheinlich OK zu sein scheint. Nun habe ich eine neue FORM DLL erstellt und den Verweis auf die Basis Klasse hinzugefügt.
In der Regel habe ich die Basis Klasse so abgeleitet:
#pragma once #include "panelklasse.h" using namespace System; using namespace System::ComponentModel; using namespace System::Collections; using namespace System::Windows::Forms; using namespace System::Data; using namespace System::Drawing; namespace Sidebar { public ref class aktienpanel : public Sidebar::panelklasse { public: aktienpanel(void) { InitializeComponent(); } ... ...
Versuche ich das ganze nun so ...
#pragma once namespace Testpanel { using namespace System; using namespace System::ComponentModel; using namespace System::Collections; using namespace System::Windows::Forms; using namespace System::Data; using namespace System::Drawing; /// <summary> /// Zusammenfassung für Form1 /// /// Warnung: Wenn Sie den Namen dieser Klasse ändern, müssen Sie auch /// die Ressourcendateiname-Eigenschaft für das Tool zur Kompilierung verwalteter Ressourcen ändern, /// das allen RESX-Dateien zugewiesen ist, von denen diese Klasse abhängt. /// Anderenfalls können die Designer nicht korrekt mit den lokalisierten Ressourcen /// arbeiten, die diesem Formular zugewiesen sind. /// </summary> public ref class aktienpanel : public PanelBasisKlasse::DLLpanelklasse { public: Form1(void) { InitializeComponent(); //
... erhalte ich folgenden Fehler:
Warnung 1 Für die angegebene Kultur oder die neutrale Kultur konnten keine Ressourcen gefunden werden. Stellen Sie sicher, dass PanelBasisKlasse.DLLpanelklasse.resources beim Kompilieren richtig in die Assembly DLLpanelklasse eingebettet wurde, oder dass die erforderlichen Satellitenassemblys geladen werden können und vollständig signiert sind. 0
Was hat dies zu bedeuten ?
-
Am liebsten wäre es mir wenn jemand noch lust hätte das ganze mal Schritt für Schritt mit mir durchzugehen. Ich versuche schon seit Stunden da hinterzusteigen. Nur will es einfach nicht gelingen.
-
shaun1981 schrieb:
Am liebsten wäre es mir wenn jemand noch lust hätte das ganze mal Schritt für Schritt mit mir durchzugehen. Ich versuche schon seit Stunden da hinterzusteigen. Nur will es einfach nicht gelingen.
machen wir das ganze mal mit etwas Pseudo-Code
Interface-Libary
Public Interface ISidepanelPlugin { UserControl ^getSidebarUC(); String ^getAuthor(); String ^getName(); // ... }
Sidepanel-Programm
verwendet Interface-Library
// ... was auch immer in der Form alles gemacht wird ArrayList<ISidepanelPlugin^> ^plugins; void LoadPlugins() { // <scanne Verzeichnis "plugins"> für jede Assembly -> lade instanziere die Klasse die das Interface implementiert packe die Instanz in die Liste } void ShowPlugins() { für jedes plugin in plugins this->Add(plugin->getSidebarUC()); }
Aktien-Plugin
verwendet Interface-Library
public class Plugin : ISidepanelPlugin { PluginUserControl ^puc = gcnew PluginUserControl(); virtual UserControl ^getSidebarUC() overrides { return puc; } String ^getAuthor() { return "icke" } String ^getName() return "Aktienkurse - 4 Tage später"; } } public Class PluginUserControl : UserControl { // was auch immer hier reingehört um Aktienkurse anzuzeigen }
hand, mogel
-
Weil ich absolut nicht mehr durchblicke, hier mal der aktuelle Stand:
interface
// Interface.h #pragma once using namespace System; using namespace System::Windows::Forms; namespace Interface { public interface class ISidepanelPlugIn { UserControl ^getSidebarUC() ; bool check (void); void InitializePanel (void); void beenden (void); }; }
DLLpanelklasse
#pragma once namespace PanelBasisKlasse { public ref class DLLpanelklasse : public System::Windows::Forms::Form { protected: static System::Collections::Generic::List<Control^> panelliste = gcnew System::Collections::Generic::List<Control^>(); ... public: void dummyadd (); public: void panellisteREFRESH (Control^ , Control^); public: DLLpanelklasse(void) { InitializeComponent(); }
Sidebar.h [Form1.h]
namespace Sidebar { public ref class Form1 : public System::Windows::Forms::Form { protected: static System::Collections::Generic::List<Interface::ISidepanelPlugIn^> plugins = gcnew System::Collections::Generic::List<Interface::ISidepanelPlugIn^>(); protected: void panelsladen (void); ... ... ... ... public: Form1(void) { InitializeComponent(); workareastandard (); bildschirmauflösung ();
Beim Laden der Assemblys stehen keine Einträge in der Result List. Das liegt wohl hieran:
Sidebar.cpp [Form1.cpp]
oid Sidebar::Form1::panelseinlesen () { using namespace System::Reflection; System::Collections::Generic::List<Interface::ISidepanelPlugIn^>^ result = gcnew System::Collections::Generic::List<Interface::ISidepanelPlugIn^>(); String^ hilfe = arbeitsordnerholen () + "PlugIns\\"; for each(String^ fileName in System::IO::Directory::GetFiles (arbeitsordnerholen () + "PlugIns\\","*.dll")) { // hier eine Fehlerbehebung für Fehler von LoadFrom System::Reflection::Assembly ^exAss = ::Reflection::Assembly::LoadFrom (fileName); for each(Type^ t in exAss->GetTypes()) { if ( t->IsPublic == true && t->IsSubclassOf (plugins.GetType ()) ) // <-- Hier scheint doch was falsch zu sein ?? { // Fehler von CreateInstance result->Add( safe_cast<Interface::ISidepanelPlugIn^>( Activator::CreateInstance(t) ) ); // vielleicht noch auf CreateInstance == null überprüfen } } } }
Jetzt das PlugIn - welches ja von der DLLpanelklasse abgeleitet werden soll, sowie auch das Interface Implementieren muss. In der DLLpanelklasse ist ein Label vorhanden, welches doch aufgrund der Ableitung auch im PlugIn selber vorhanden sein sollte.
Die Sache mit dem UserControl kann ich noch nicht ganz nachvollziehen, obwohl der Designer mir dabei zumindest schon mal das bearbeiten ohne Exception erlaubt.
#pragma once ... namespace Forms { ref class PlugIn; public ref class Testpanel : UserControl { public: Testpanel(void) { InitializeComponent(); } protected: ~Testpanel() { if (components ... ... ... #pragma region Windows Form Designer generated code void InitializeComponent(void) { System::ComponentModel::ComponentResourceManager^ resources = (gcnew System::ComponentModel::ComponentResourceManager(Testpanel::typeid)); this->SuspendLayout(); // // Testpanel // this->AutoScaleDimensions = System::Drawing::SizeF(6, 13); this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font; this->BackgroundImage = (cli::safe_cast<System::Drawing::Image^ >(resources->GetObject(L"$this.BackgroundImage"))); this->Name = L"Testpanel"; this->Size = System::Drawing::Size(180, 140); this->ResumeLayout(false); } #pragma endregion }; public ref class PlugIn : Interface::ISidepanelPlugIn , PanelBasisKlasse::DLLpanelklasse { public: virtual UserControl^ getSidebarUC () { return safe_cast<UserControl^>(Activator::CreateInstance ( this->GetType () ) ); } public: virtual bool check (void) { return true; }; public: virtual void InitializePanel (void) { }; public: virtual void beenden (void) { }; }; }
Ich hoffe ihr werdet - nachdem ihr das gesehen habt - nicht die Hände über dem Kopf zusammenschlagen
-
shaun1981 schrieb:
Weil ich absolut nicht mehr durchblicke, hier mal der aktuelle Stand:
pack mal alles in eine ZIP und poste mal den Link zum Download ... ich versuche heute noch reinzuschauen - wenn mich mein Terrorist läßt
String^ hilfe = arbeitsordnerholen () + "PlugIns\\";
wenn das Verzeichnis im Verzeichnis des Programms liegt (also als Unterordner), dann brauchst Du den Arbeitsordner nicht ... im Normalfall kannst Du immer vom PRogrammverzeichnis aus direkt (also relativ) auf die Unterordner zugreifen
Beim Laden der Assemblys stehen keine Einträge in der Result List. Das liegt wohl hieran:
if ( t->IsPublic == true && t->IsSubclassOf (plugins.GetType ()) )
ich weis jetzt nicht woher Du plugins hast ... aber da sollte ISidepanelPlugIn stehen
Jetzt das PlugIn - welches ja von der DLLpanelklasse abgeleitet werden soll, sowie auch das Interface Implementieren muss. In der DLLpanelklasse ist ein Label vorhanden, welches doch aufgrund der Ableitung auch im PlugIn selber vorhanden sein sollte.
ich habe das Gefühl das Du hier Interface->Basis-Klasse->Plugin-Klasse machst ... dann kannst Du prinzipell auch das Interface weglassen und die Basis-Klasse abstrakt machen ... hat den gleichen Effekt
Die Sache mit dem UserControl kann ich noch nicht ganz nachvollziehen, obwohl der Designer mir dabei zumindest schon mal das bearbeiten ohne Exception erlaubt.
was ist da unklar?
Ich hoffe ihr werdet - nachdem ihr das gesehen habt - nicht die Hände über dem Kopf zusammenschlagen
doch :p ... irgendwie muss ich was falsch erklären
hand, mogel
-
pack mal alles in eine ZIP und poste mal den Link zum Download ... ich versuche heute noch reinzuschauen - wenn mich mein Terrorist läßt
Ein Lichtblick.
String^ hilfe = arbeitsordnerholen () + "PlugIns\";
wenn das Verzeichnis im Verzeichnis des Programms liegt (also als Unterordner), dann brauchst Du den Arbeitsordner nicht ... im Normalfall kannst Du immer vom PRogrammverzeichnis aus direkt (also relativ) auf die Unterordner zugreifen
Ratschlag angenommen.
Beim Laden der Assemblys stehen keine Einträge in der Result List. Das liegt wohl hieran:
C++/CLI:
if ( t->IsPublic == true && t->IsSubclassOf (Interface::ISidepanelPlugIn) )ich weis jetzt nicht woher Du plugins hast ... aber da sollte ISidepanelPlugIn stehen
plugins ist so definiert:
protected: static System::Collections::Generic::List<Interface::ISidepanelPlugIn^> plugins = gcnew System::Collections::Generic::List<Interface::ISidepanelPlugIn^>();
for each(Type^ t in exAss->GetTypes()) { if ( t->IsPublic == true && t->IsSubclassOf (Interface::ISidepanelPlugIn))) { //Fehler von CreateInstance result->Add( safe_cast<Interface::ISidepanelPlugIn^>( Activator::CreateInstance(t) ) ); //vielleicht noch auf CreateInstance == null überprüfen }
...erhalte ich
Fehler 1 error C2275: 'Interface::ISidepanelPlugIn': Ungültige Verwendung dieses Typs als Ausdruck d:\C++ Backup\Sidebar\Sidebar\Form1.cpp 71
Aber der gefragte Typ ist doch "Interface::SidepanelPlugIn" - oder irre ich mich da?
-
Also,
Du hast alle Deine Plugins im Hauptprogramm mit drinnen ... wenn Du wirklich Plugins machen willst, dann sollten die raus in jeweils eine eigene DLL ... aber Du scheinst das ganze Prinzip noch nicht so richtig verstanden zu haben
ein Vorschlag von meiner Seite ... leg Dein aktuelles Projekt mal zur Seite ... fange ein neues Projekt zum Üben an ... eine DLL die das Interface enthält ... eine Programm was die Plugins nachläd ... und je eine DLL für das Plugin ... es geht hier nur darum das Du übst um das Prinzip zu verstehen ... Plugins haben nichts weiter zu tun als mit Vererbung - nur über mehrere Dateien verstreut
wenn Du das Prinzip verstanden hast, dann kannst Du Dein Projekt neu aufbauen
im übrigen hast kannst Du UserControls verwenden für die einzelnen Plugins ... bei mir war Dein Sidebar-Fenster offen ... dann kam meine Sidebar (die von Vista) und dann kamen die einzelnen Fenster von den Plugins ... wenn Du die auf UserControls änderst, dann kannst Du die mit
form1->Controls->Add( ... )
hinzufügen
dann hängen die auch immer zusammen
hand, mogel
-
Ich muss dir recht geben, dass ich einige Fehler begangen habe. Habe die Sidebar mal eben so angefangen - und mich erst in einem recht späten Stadium dazu entschlossen, mich doch mit einem PlugIn Mechanismus auseinanderzusetzen.
Aber daraus kann ich nur lernen. Die PlugIns sind natürlich zu früherer Stunde entstanden - und wurden dann einfach instanziert. Als ich mich entschlossen habe das ganze via DLL zu lösen, habe ich dann einfach das laden der Panels unterbunden, und das ganze mit den dir ja bekannten Funktionen zu erledigen.
Das Problem mit dem überlagern der Form usw. steht auch schon auf meiner Liste. Gefällt mir auch nicht. Das passiert eben bei einer NULL Planung. Die UserControls sind seit gestern ein völlig neuer Aspekt, in den ich mich erst mal einarbeiten muss.
Aber ich würde auf jeden Fall gerne DIESES Problem behoben wissen, oder hällst du das nicht sinnvoll? Lieber wärs mir schon.
-
shaun1981 schrieb:
Das Problem mit dem überlagern der Form usw. steht auch schon auf meiner Liste. Gefällt mir auch nicht. Das passiert eben bei einer NULL Planung. Die UserControls sind seit gestern ein völlig neuer Aspekt, in den ich mich erst mal einarbeiten muss.
UserControl ist prinzipell nur eine Form ohne Fensterrahmen ... ansonsten ändert sich nix
Aber ich würde auf jeden Fall gerne DIESES Problem behoben wissen, oder hällst du das nicht sinnvoll? Lieber wärs mir schon.
ob es sich lohn das ganze in Plugins auszulagern - ja sicher ... ich habe auch schon überlegt eine Sidebar zu basteln - da die unter Windows 7 wieder entfernt wurde (AFAIK) - aber habe keine Zeit dazu ... und da hätte ich auch wieder mit Plugins gearbeitet ... könnte ja sein das die Sidebar mal berühmt wird
... und bevor 20.000 Menschen am Quelltext pfuschen macht sich da alles als Plugin einfacher
hand, mogel
-
Also dann kann ich mein Projekt ja gleich zum Wind schießen. Du schnippst dir das wohl mal eben aus dem Finger was
? Aber nun lass dir doch nicht alles aus der Nase ziehen. Was mache ich denn so Falsch?
-
shaun1981 schrieb:
Also dann kann ich mein Projekt ja gleich zum Wind schießen.
nein - wieso?
Du schnippst dir das wohl mal eben aus dem Finger was
?
nein - reine Übungssache ... Datenbanken beschränkt sich bei mir nur auf SELECT & Co. ... ich weis das es Transaktionen gibt - aber noch nie verwenden müssen ... also den ganzen SQL-Kram aus dem Framework habe ich noch nie verwendet ... und unter Java spreche ich MySQL auch nur mit den SELECT's und fische alles einzeln
Aber nun lass dir doch nicht alles aus der Nase ziehen. Was mache ich denn so Falsch?
Du sollts einfach mal üben ... Du kannst zum Beispiel Calculon erweitern (auch wenns VB.NET ist - oder setze es erstmal auf C++/CLI um) ... weitere Operationen (also Plugins) hinzufügen ... dann das Interface erweitern und die Plugins entsprechend anpassen ... zum Beispiel könnten die Plugins ein UserControl mit einer Grafik zurück liefern - das Du dann entsprechend auf der Form anzeigen kannst
wenn Du dann das Prinzip verstanden hast, dann kannst Du Deine Struktur für Deine Sidebar nochmal überdenken bzw. überarbeiten ... und dann den Plugin-Mechanismuss für die Plugins umsetzen
hand, mogel
-
Nun wollte ich ein kleines Übungsprojekt starten - um der Sache mit den Interfaces näher zu kommen, und habe gleich ein mir neues - völlig unerklärliches Problem:
Ich möchte nun das Interface erstellen, klicke auf neues Projekt, Win32 - Projekt, DLL und Leeres Projekt. Dann erstelle ich ein neues Headerfile und schreibe den ja bekannten Code hinein:
namespace Interface { public interface ref class Schnittstelle { ... }; }
Das versuche ich zu kompilieren und erhalte folgenden Fehler:
Fehler 1 general error c10100b1: Failed to load file "..\Debug\hilfsprojekt.dll". The system cannot find the path specified. mt.exe
Das passiert bei jedem Projekt. Die DLL wird einfach nicht erstellt und ist im Ordner demnach auch nicht vorhanden. Ich kann mir das absolut nicht erklären - woran das auf einmal liegen sollte.
Habe auch schon versucht das Ausgabeverzeichniss zu ändern - aber auch das hilft mir nicht.
Buildprotokoll Neu erstellen wurde gestartet: Projekt: "hilfsprojekt", Konfiguration: "Debug|Win32"
Befehlszeilen Die temporäre Datei "c:\Users\Jan\Documents\Visual Studio 2008\Projects\DLLinterface\hilfsprojekt\Debug\RSP0002A519003424.rsp" wird erstellt. Inhalt:
[
/outputresource:"..\Debug\hilfsprojekt.dll;#2" /manifest".\Debug\hilfsprojekt.dll.intermediate.manifest"
]Erstellen der Befehlszeile "mt.exe @"c:\Users\Jan\Documents\Visual Studio 2008\Projects\DLLinterface\hilfsprojekt\Debug\RSP0002A519003424.rsp" /nologo" Ausgabefenster Das Manifest wird eingebettet...
mt.exe : general error c10100b1: Failed to load file "..\Debug\hilfsprojekt.dll". The system cannot find the path specified.
Ergebnisse Das Buildprotokoll wurde unter "file://c:\Users\Jan\Documents\Visual Studio 2008\Projects\DLLinterface\hilfsprojekt\Debug\BuildLog.htm" gespeichert.
hilfsprojekt - 1 Fehler, 0 Warnung(en)Eine Idee hierzu ?
-
ich tippe dann nochmal auf "Erstellen" (nicht "Neu Erstellen") ... beim Zweiten mal passt alles ... scheint aber ein generelles Problemzu sein ... MS wird das wohl in VS2010 fixen ... hast Du den Header schon in eine CPP eingebunden?