カテゴリー別アーカイブ: Managed Extensibility Framework

【F# + ASP.NET MVC】 MEFによるDIを行うには

◆ DI用インターフェース

namespace PluginInterface

type IPlugin =
   abstract member Execute : string

◆ DI用オブジェクト(DLLファイル)

namespace PluginModule

open System
open System.ComponentModel.Composition
// DI用インターフェース
open PluginInterface

// Export属性でDI対象オブジェクトを設定
[<Export(typeof<IPlugin>)>]
type PluginModule1() =
    interface IPlugin with
        // インターフェース メソッド
        member this.Execute = "Hello Plugin!"

◆ Global.fs

namespace Sample.Routing

open System
open System.Web
open System.Web.Mvc
open System.Web.Routing
open System.ComponentModel.Composition
open System.ComponentModel.Composition.Hosting
open System.Reflection

open Sample.Mef
open Sample.Controllers

type Route = { controller : string
               action : string
               id : UrlParameter }

type Global() =
    inherit System.Web.HttpApplication() 

    static member RegisterRoutes(routes:RouteCollection) =
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}")
        routes.MapRoute("Default", 
                        "{controller}/{action}/{id}", 
                        { controller = "Home"; action = "Index"
                          id = UrlParameter.Optional } )

    member this.Start() =
        AreaRegistration.RegisterAllAreas() 
        Global.RegisterRoutes(RouteTable.Routes) |> ignore

        // カタログを登録
        let catalog = new AggregateCatalog()
        // 対象ディレクトリ内のファイルからカタログを取得
        catalog.Catalogs.Add(
            new DirectoryCatalog(base.Server.MapPath("Plugins"), "*.dll"))
        // アセンブリ内のカタログを取得
        catalog.Catalogs.Add(
            new AssemblyCatalog(Assembly.GetExecutingAssembly()))
        // コンテナを生成        
        let container = new CompositionContainer(catalog)
        container.ComposeParts(this)
        // Export属性のオブジェクトから依存情報を取得
        DependencyResolver.SetResolver(new MefDependencySolver(container))

        

◆ MEFのExport属性オブジェクトから依存情報を取得

namespace Sample.Mef

open System
open System.Collections.Generic
open System.ComponentModel.Composition
open System.ComponentModel.Composition.Hosting
open System.Web.Mvc

type MefDependencySolver(compositionContainer : CompositionContainer) as this =
    do this.CompositionContainer <- compositionContainer
        
    [<DefaultValue>]
    val mutable _compositionContainer : CompositionContainer
    
    member public this.CompositionContainer
        with get() = this._compositionContainer
        and set v = this._compositionContainer <- v

    interface IDependencyResolver with
        member this.GetService(serviceType : Type) : obj =
            let name = AttributedModelServices.GetContractName(serviceType)
            this.CompositionContainer.GetExportedValueOrDefault<obj>(name)

        member this.GetServices(serviceType : Type) : IEnumerable<obj> =
            this.CompositionContainer.GetExportedValues<obj>
                (serviceType.FullName)
    
    
    

◆ Controller

namespace Sample.Controllers

open System.Web
open System.Web.Mvc
open System.Web.SessionState
open System.ComponentModel.Composition
open System.ComponentModel.Composition.Hosting
open PluginInterface

[<Export>]
type HomeController() =
    inherit Controller()
    
    [<DefaultValue>]
    val mutable _plugin : IPlugin
    
    // Import属性でDI対象オブジェクトを設定
    [<Import>]
    member public x.Plugin
        with get() = x._plugin
        and set v = x._plugin <- v

    member this.Index() =
        // DIされたオブジェクトのメソッドを実行
        this.ViewData.["Message"] <- this.Plugin.Execute
        this.View() :> ActionResult

広告

【F# + ASP.NET MVC】 MEFによるプラグイン開発を行うには

◆ プラグイン用インターフェース

namespace PluginInterface

type IPlugin =
   abstract member Execute : string

◆ プラグイン(DLLファイル)

namespace PluginModule

open System
open System.ComponentModel.Composition
// プラグイン用インターフェース
open PluginInterface

// Export属性で、プラグイン用インターフェース型を設定
[<Export(typeof<IPlugin>)>]
type PluginModule1() =
    interface IPlugin with
        // インターフェース メソッド
        member this.Execute = "Hello Plugin!"

◆ MEFで動的にDLLファイルを読み込む

namespace Sample.Controllers

open System.Web
open System.Web.Mvc
open System.Web.SessionState
open System.ComponentModel.Composition
open System.ComponentModel.Composition.Hosting
open PluginInterface

type HomeController() =
    inherit Controller()
    
    [<DefaultValue>]
    val mutable plugin : IPlugin
    
    // Import属性で、プラグイン用インターフェース型を設定
    [<Import(typeof<IPlugin>)>]
    member public x.Plugin
        with get() = x.plugin
        and set v = x.plugin <- v

    member this.Index() =
        // binディレクトリよりカタログを検出(プラグイン用DLLをbinディレクトリに配置)
        let catalog =
            new DirectoryCatalog(HttpRuntime.BinDirectory, "PluginModule.dll")
        // カタログを用いてコンテナからパーツを検出
        let container = new CompositionContainer(catalog)
        this.Plugin <- container.GetExportedValue<IPlugin>()
        // プラグインのインターフェース メソッドを実行
        this.ViewData.["Message"] <- this.Plugin.Execute
        this.View() :> ActionResult

【MEF】Silverlightで、プラグイン(xap)開発を行うには

◆ プラグイン用インターフェース

namespace PluginInterface
{
    public interface IPlugin
    {
        void Execute();
    }
}

◆ プラグイン(xap)

using System;
using System.Windows;
using System.Windows.Controls;
// System.ComponentModel.Composition.dll を参照設定
using System.ComponentModel.Composition;
// プラグイン用インターフェース プロジェクトを参照設定
using PluginInterface;

namespace SilverlightPlugin
{
    // Export属性で、プラグイン用インターフェース型を設定
    [Export("Plugin", typeof(IPlugin))]
    public partial class MainPage : UserControl, IPlugin 
    {
        public MainPage()
        {
            InitializeComponent();
        }

        void IPlugin.Execute()
        {
            MessageBox.Show("Hello Plugin!");
        }
    }    
}

◆ Managed Extensibility Frameworkで、動的にxapファイルを読み込む

using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
// System.ComponentModel.Composition.dll を参照設定
// System.ComponentModel.Composition.Initialization.dll を参照設定
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
// プラグイン用インターフェース プロジェクトを参照設定
using PluginInterface;

namespace SilverlightApplication3
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
        }

        // ImportMany属性で、プラグイン用インターフェース型を設定
        [ImportMany("Plugin", typeof(IPlugin), AllowRecomposition = true)]
        public List<IPlugin> plugins;

        private void OnLoaded(object sender, RoutedEventArgs e)
        {
            // プラグイン「SilverlightPlugin.xap 」は、
            //     Webプロジェクトの「ClientBin」フォルダへ格納しておく
            CompositionHost.Initialize(
                CreateCatalog("SilverlightPlugin.xap") );
            // ImportMany属性が指定された変数へ Export属性のインスタンスを格納する
            CompositionInitializer.SatisfyImports(this);
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            // プラグインのExecuteメソッドを呼び出す
            plugins[0].Execute();
        }

        // xapファイルのダウンロード
        private DeploymentCatalog CreateCatalog(string uri)
        {
            var deploymentCatalog = new DeploymentCatalog(uri);
            deploymentCatalog.DownloadAsync();
            return deploymentCatalog;
        }
    }
}