Mekanisme refleksi yang disediakan oleh .NET dapat dengan mudah memuat plug-in. Artikel ini memberikan metode yang dapat memuat plug-in yang diperlukan secara fleksibel dan benar.
Di .NET, nama tipe lengkap memiliki format "nama tipe, nama rakitan".
Misalnya: "System.Configuration.NameValueSectionHandler, Sistem, Versi=1.0.3300.0, Budaya=netral, PublicKeyToken=b77a5c561934e089".
Nama tipenya adalah: System.Configuration.NameValueSectionHandler, yang merupakan nama tipe lengkap dengan namespace.
Anda juga bisa mendapatkan Nama Lengkap menggunakan tipe.
Misalnya: string typeName = typeof(NameValueSectionHandler).FullName;
Nama perakitannya adalah: "Sistem, Versi=1.0.3300.0, Budaya=netral, PublicKeyToken=b77a5c561934e089",
Rakitan tersebut diberi nama Sistem, dan sistem secara otomatis menyesuaikan ekstensinya (seperti System.dll atau System.exe);
Versi, Budaya, dan PublicKeyToken adalah versi spesifik, latar belakang budaya, dan tanda tangan kumpulan. Tidak ada persyaratan khusus, dan ini dapat dihilangkan.
Kita dapat secara dinamis memuat tipe yang diperlukan berdasarkan nama tipe tersebut. menyukai:
string typeName = "Sistem.Konfigurasi.NameValueSectionHandler, Sistem";
Ketik t = Tipe.GetType(typeName);
Obj objek = Activator.CreateInstance(t);
//atau
System.Configuration.NameValueSectionHandler obj = (System.Configuration.NameValueSectionHandler)Activator.CreateInstance(t);
Pada titik ini, obj adalah tipe instance yang diperlukan.
Biasanya plug-in adalah kelas yang perlu mengimplementasikan antarmuka tertentu. Oleh karena itu, sebelum memuat plugin, Anda perlu menentukan apakah jenis plugin tersebut sesuai.
Misalnya, jika antarmuka sebuah plug-in adalah IPlugin, kita dapat mengidentifikasinya dengan cara berikut:
string interfaceName = typeof(IPlugin).Nama Lengkap;
string typeName = "Muf.Plugin Saya, Plugin Saya";
Ketik t = Tipe.GetType(typeName);
jika ( t == nol
||.!t.IsClass
||. !t.IsPublik
||.t.GetInterface(namaantarmuka) == null)
{
return null; // Bukan plugin yang diperlukan
}
Meringkas kode di atas, kita dapat membuat kode umum untuk memuat plug-in:
/**//// <ringkasan>
/// Memuat dan membuat tipe secara dinamis yang memiliki antarmuka tertentu
/// </ringkasan>
/// <param name="className">Ketik nama</param>
/// <param name="interfaceName">Nama antarmuka yang ditentukan</param>
/// <param name="param">Tentukan parameter konstruktor (array kosong atau kosong berarti memanggil konstruktor default)</param>
/// <returns>Mengembalikan tipe yang dibuat (null berarti tipe tidak dapat dibuat atau tidak dapat ditemukan)</returns>
objek statis publik LoadObject(string className, string interfaceName, objek[] param)
{
mencoba
{
Ketik t = Tipe.GetType(namakelas);
jika ( t == nol
||.!t.IsClass
||. !t.IsPublik
||.t.IsAbstrak
||.t.GetInterface(namaantarmuka) == null)
{
kembalikan nol;
}
objek o = Aktivator.CreateInstance(t, param);
jika( o == nol )
{
kembalikan nol;
}
kembali o;
}
menangkap (Pengecualian ex)
{
kembalikan nol;
}
}
Nanti, kita bisa menggunakan LoadObject untuk memuat plugin apa pun yang diperlukan.
Plug-in umumnya ditempatkan di file konfigurasi dan dibaca oleh program:
Contoh file konfigurasi (lihat esai terkait saya untuk penggunaan file konfigurasi):
<?xml version="1.0" coding="utf-8" ?>
<konfigurasi>
<configBagian>
<section name="Channels" type="Vmp.Configuration.ChannelsSectionHandler, Komunikasi" />
</configBagian>
<Saluran>
<saluran
ChannelType="Vmp.Communication.TcpChannel, Komunikasi"
JejakFile="d:logchannel1.log"
Port="2020" MaxConnections="300" BufferSize="2048"
/>
</Saluran>
</konfigurasi>
Contoh kode:
private ArrayListchannelsList = new ArrayList();
private LoadChannels();
{
ArrayListchannelConfig = (ArrayList)ConfigurationSettings.GetConfig( "Saluran" );
foreach (konfigurasi Hashtable dichannelConfig)
{
string channelType = (string) config["ChannelType"];
IChannel channel = (IChannel) CommonUtils.LoadObject(channelType, typeof(IChannel).FullName, objek baru[]{config});
jika(saluran == nol)
lanjutkan;
daftar saluran.Tambahkan(saluran);
}
Anda juga dapat melintasi direktori plug-in yang ditentukan dan memuat semua plug-in yang memenuhi persyaratan, misalnya:
public IPlugin[] LoadAllPlugIn(string pluginDir)
{
//Setel direktori plugin default
jika(pluginDir == null || pluginDir == "")
pluginDir = "./PlugIns";
// Dapatkan nama antarmuka plugin
string interfaceName = typeof(IPlugin).FullName;
// Array yang digunakan untuk menyimpan plug-in
ArrayList arr = new ArrayList();
// Melintasi direktori plug-in (dengan asumsi plug-in adalah file dll)
foreach(file string di Directory.GetFiles(pluginDir, "*.dll"))
{
//Muat file plugin
Majelis asm = Majelis.LoadFile(file);
// Melintasi kelas plug-in yang diekspor
foreach(Ketik t di asm.GetExportedTypes())
{
//Muat plugin. Jika plugin tidak sesuai dengan antarmuka yang ditentukan, kembalikan null
Plugin IPlugin = LoadObject(t.FullName, interfaceName, null) sebagai IPlugin
jika(plugin != null)
arr.Tambahkan(plugin);
}
}
// Kembali ke plugin
return (IPlugin[])arr.ToArray(typeof(IPlugin));
}