HOW TO:使用反映實作外掛程式元件架構 (C++/CLI)
下列程式碼範例會示範使用反映以實作簡單的「外掛程式」架構。 第一個列表是應用程式,第二個是外掛程式。 應用程式是多重文件表單,會使用任何在外掛程式 DLL (以命令列引數的方式提供) 中找到的表單架構類別,將資料填入表單。
應用程式會使用 Assembly.Load 方法,嘗試載入提供的組件。 如果成功,則會使用 Assembly.GetTypes 方法列舉組件中的型別。 接著使用 Type.IsAssignableFrom 方法檢查每個型別的相容性。 在這個範例中,在提供的組件中找到的類別必須衍生自 Form 類別,才會視為外掛程式。
接著相容的類別會以 Activator.CreateInstance 方法執行個體化,此方法可接受 Type 做為引數並會傳回新執行個體的指標。 每個新的執行個體會附加至表單並顯示在表單中。
請注意 Load 方法不接受含有副檔名的組件名稱。 因為應用程式的主函式會修剪掉任何提供的副檔名,所以不管組件名稱有無副檔名,下列程式碼範例都可以運作。
範例
下列程式碼定義接受外掛程式的應用程式。 必須提供組件名稱做為第一個引數。 這個組件應該包含至少一個公用的 Form 衍生型別。
// plugin_application.cpp
// compile with: /clr /c
#using <system.dll>
#using <system.drawing.dll>
#using <system.windows.forms.dll>
using namespace System;
using namespace System::Windows::Forms;
using namespace System::Reflection;
ref class PluggableForm : public Form {
public:
PluggableForm() {}
PluggableForm(Assembly^ plugAssembly) {
Text = "plug-in example";
Size = Drawing::Size(400, 400);
IsMdiContainer = true;
array<Type^>^ types = plugAssembly->GetTypes( );
Type^ formType = Form::typeid;
for (int i = 0 ; i < types->Length ; i++) {
if (formType->IsAssignableFrom(types[i])) {
// Create an instance given the type description.
Form^ f = dynamic_cast<Form^> (Activator::CreateInstance(types[i]));
if (f) {
f->Text = types[i]->ToString();
f->MdiParent = this;
f->Show();
}
}
}
}
};
int main() {
Assembly^ a = Assembly::LoadFrom("plugin_application.exe");
Application::Run(gcnew PluggableForm(a));
}
下列程式碼定義三個衍生自 Form 的類別。 當產生的組件名稱傳遞至上面列表中的可執行檔時,雖然在編譯時期這些類別對裝載的應用程式是未知的,應用程式還是會探索並執行個體化這三個類別。
// plugin_assembly.cpp
// compile with: /clr /LD
#using <system.dll>
#using <system.drawing.dll>
#using <system.windows.forms.dll>
using namespace System;
using namespace System::Windows::Forms;
using namespace System::Reflection;
using namespace System::Drawing;
public ref class BlueForm : public Form {
public:
BlueForm() {
BackColor = Color::Blue;
}
};
public ref class CircleForm : public Form {
protected:
virtual void OnPaint(PaintEventArgs^ args) override {
args->Graphics->FillEllipse(Brushes::Green, ClientRectangle);
}
};
public ref class StarburstForm : public Form {
public:
StarburstForm(){
BackColor = Color::Black;
}
protected:
virtual void OnPaint(PaintEventArgs^ args) override {
Pen^ p = gcnew Pen(Color::Red, 2);
Random^ r = gcnew Random( );
Int32 w = ClientSize.Width;
Int32 h = ClientSize.Height;
for (int i=0; i<100; i++) {
float x1 = w / 2;
float y1 = h / 2;
float x2 = r->Next(w);
float y2 = r->Next(h);
args->Graphics->DrawLine(p, x1, y1, x2, y2);
}
}
};