【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

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中