[seasar-dotnet:718] S2ContainerのASP.NETでの利用について

Hiroki Inoue [E-MAIL ADDRESS DELETED]
2007年 12月 28日 (金) 01:35:10 JST


初めまして、井上と申します。

初めてのDIコンテナとしてSeasar2を勉強中なのですが、ASP.NETでS2Containerを
利用するにあたり、2点ご教授いただきたいことがあります。
「http://s2container.net.seasar.org/ja/asp.html」に記述のある、リクエストの
自動バインディングとWebフォームに対してのDIです。
対象バージョンは最新の1.3.5です。

まず、リクエストの自動バインディングですが、HttpRequestをバインディングするには
コンポーネント中にプロパティ(SET)を定義するだけで自動バインディングされる、と
書かれていますが、手動はできても自動がうまくいきません。
試したプログラムは次のとおりです。言語はVB.NETです。

App_Data/sample.dicon(抜粋)
-----
<component
  name="SampleLogic"
  class="Sample.Web.Logic.SampleLogic"
  instance="request"/>
-----

App_Code/SampleCode.vb
-----
Imports Microsoft.VisualBasic
Imports Seasar.Framework.Container

Namespace Sample.Web.Logic
    Public Interface ISampleLogic
        Function GetSampleValue() As String
    End Interface

    Public Class SampleLogic : Implements ISampleLogic
        Private req As HttpRequest
        Private con As IS2Container

        Public WriteOnly Property Request() As HttpRequest
            Set(ByVal value As HttpRequest)
                req = value
            End Set
        End Property

        Public WriteOnly Property Container() As IS2Container
            Set(ByVal value As IS2Container)
                con = value
            End Set
        End Property

        Public Function GetSampleValue() As String _
            Implements ISampleLogic.GetSampleValue

            Return req.UserAgent
        End Function

    End Class
End Namespace
-----

Default.aspx.vb(抜粋)
-----
Protected Sub Page_Load( _
    ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

    Dim c As IS2Container = SingletonS2ContainerFactory.Container()
    Dim s As ISampleLogic = c.GetComponent(GetType(ISampleLogic))

    Label1.Text = s.GetSampleValue()
End Sub
-----

「SampleLogic」というコンポーネントを定義して「Default.aspx」で使うのですが、
実行すると「SampleLogic」の「GetSampleValue()」の「req」で「NullReference
Exception」が起きます。確かに「req」のインスタンスは「Nothing」でした。

同じように定義してある「con」には「Seasar.Framework.Container.Impl.
S2ContainerImpl」のインスタンスが入っていました。
そこで、試しに「sample.dicon」で次のように手動バインディングするように
変更したら動作しました。
-----
<component
  name="SampleLogic"
  class="Sample.Web.Logic.SampleLogic"
  instance="request">
    <property name="Request">request</property>
    <property name="Container">container</property>
</component>
-----

「container」には「Request」を持っているので「GetSampleValue()」で
「con.Request.UserAgent」としたり、極端な話バインディングしなくても
「HttpContext.Current」からとれるので別に困りはしない
のですが…。
自動バインディングのやり方が間違っているのでしょうか?


2つ目のWebフォームに対してのDIについてですが、コンポーネント定義はパスを
使って「instance="outer"」で定義すればよいようですが、うまくいきません…。
試したプログラムは上のものを変更して次のとおりです。

App_Data/sample.dicon(抜粋)
-----
<component name="/Default.aspx" instance="outer"/>
-----

Default.aspx.vb(抜粋)
-----
Private obj As ISampleLogic

Public WriteOnly Property SampleLogic() As ISampleLogic
    Set(ByVal value As ISampleLogic)
        obj = value
    End Set
End Property

Protected Sub Page_Load( _
    ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

    SingletonS2ContainerFactory.Container(). _
    InjectDependency(Me, "/Default.aspx")

    Label1.Text = obj.GetSampleValue()
End Sub
-----

受け口としてのプロパティをWebフォームのクラスに用意し、「Page_Load」で
「InjectDependency」をしています。
「InjectDependency」は実行してもエラーなく通るのですが、「obj」にDIされて
いません。手動バインディングしようとしても「JScriptEvaluateRuntimeException」
が発生してうまくいきませんでした。

「outer」の扱い自体が間違っているのかと思い、「Dummy」というクラスを作成
して、それを「outer」のコンポーネントとして「InjectDependency」してみたの
ですが、これはうまくいきました。次のとおりです。

App_Data/sample.dicon(抜粋)
-----
<component
  name="Dummy"
  class="Sample.Web.Logic.Dummy"
  instance="outer"/>
-----

Dummy.vb
-----
Imports Microsoft.VisualBasic
Imports Seasar.Framework.Container.Factory

Namespace Sample.Web.Logic
    Public Interface IDummy
        Function GetSampleValueByDummy() As String
    End Interface

    Public Class Dummy : Implements IDummy
        Private obj As ISampleLogic

        Public WriteOnly Property SampleLogic() As ISampleLogic
            Set(ByVal value As ISampleLogic)
                obj = value
            End Set
        End Property

        Public Sub New()
            SingletonS2ContainerFactory.Container(). _
            InjectDependency(Me, "Dummy")
        End Sub

        Public Function GetSampleValueByDummy() As String _
            Implements IDummy.GetSampleValueByDummy

            Return obj.GetSampleValue()
        End Function
    End Class
End Namespace
-----

-----
Protected Sub Page_Load( _
    ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

    Dim d As IDummy = New Dummy()
    Label1.Text = d.GetSampleValueByDummy()
End Sub
-----

「/Default.aspx」コンポーネントに対しても、「Dummy」コンポーネント
に対しても、「outer」で同じように内部で「InjectDependency」している
つもりなのですが、前者は失敗、後者は成功です。
WebフォームへのDIに対する考え方が間違っているのでしょうか?
参考資料をいろいろ探してみたのですが、自力解決できませんでした。

初歩的な内容なのかもしれませんが、よろしくお願いします。


seasar-dotnet メーリングリストの案内