Pluginの実装4
Pluginのロード・アンロード処理です。
ロードのキモになるのは次のGatewayクラスです。
class Gateway : MarshalByRefObject { public IWidget CreateInstance(string location, string className) { Assembly assembly = Assembly.LoadFrom( location ); return ( (IWidget)assembly.CreateInstance( className ) ); } }
メインのアプリケーションドメインからはWidget毎のアプリケーションドメインを作成し、Gatewayクラスのインスタンスを作成します。
GatewayクラスはMarshalByRefObjectなので、proxy経由でWidgetのアプリケーションドメインで実行されます。
PluginアセンブリのロードはWidget用アプリケーションドメインのみで行われるため、アプリケーションドメインをアンロードすることによりアセンブリのアンロードが可能となります。
以下、WidgetPluginのロード・アンロードに関する処理部です。
private AppDomain domain = null; private Gateway gateway = null; public void Load() { if ( this.domain != null ) { return; } try { this.domain = AppDomain.CreateDomain( "WidgetDomain_" + Name ); } catch { AppDomain.Unload( this.domain ); this.domain = null; return; } this.gateway = (Gateway)this.domain.CreateInstanceAndUnwrap( "UsaWidget.Plugin", "UsaWidget.Plugin.Gateway" ); } public void Unoad() { if ( this.domain == null ) { return; } this.gateway = null; AppDomain.Unload( this.domain ); } public IWidget CreateWidget() { if ( this.gateway == null ) { return( null ); } IWidget widget = this.gateway.CreateInstance( this.location, this.className ); return( widget ); }
割といいかげんな実装ですが…(´・ω・`)
なお、IWidget実装クラスもproxy経由でアクセスできるように、MarshalByRefObjecとして実装します。