3

ASP.net ベースの Web アプリケーション用に spring.net 4.0 、 nhibernate 3.0 を使用して Web アプリケーションを開発した経験があります。WorkerRole最近、クラスに属するサービスの依存関係を注入するために spring.net を使用する必要がある状況に遭遇しました。春のweb.configファイルで通常行ったように、app.configファイルを作成しました。これは明確にするためです。(ルートノードを除外しました)

<configSections>
    <sectionGroup name="spring">
      <section name="context" type="Spring.Context.Support.WebContextHandler, Spring.Web" requirePermission="false" />
      <section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" requirePermission="false" />
      <section name="parsers" type="Spring.Context.Support.NamespaceParsersSectionHandler, Spring.Core" />
    </sectionGroup>
  </configSections>
    <spring>
    <context>
      <!-- Application services and data access that has been previously developed and tested-->
      <resource uri="assembly://DataAccess/data-access-config.xml" />
      <resource uri="assembly://Services/service-config.xml" />
      <resource uri="AOP.xml" />
      <resource uri="DI.xml"/>
    </context>
    <parsers>
      <parser type="Spring.Data.Config.DatabaseNamespaceParser, Spring.Data" />
      <parser type="Spring.Transaction.Config.TxNamespaceParser, Spring.Data" />
      <parser type="Spring.Aop.Config.AopNamespaceParser, Spring.Aop" />
    </parsers>
  </spring>

同様に、AOP.xml は次のとおりです。

<object id="FilterServiceProxy" type="Spring.Aop.Framework.ProxyFactoryObject, Spring.Aop">
    <property name="proxyInterfaces" value="Domain.IFilterService"/>
    <property name="target" ref="FilterService"/>
    <property name="interceptorNames">
      <list>
        <value>UnhandledExceptionThrowsAdvice</value>
        <value>PerformanceLoggingAroundAdvice</value>
      </list>
    </property>
  </object>
</objects>

およびDI.xml

<object type="FilterMt.WorkerRole, FilterMt" >
  <property name="FilterMtService1" ref="FilterServiceProxy"/>
</object>

ただし、worker ロールに依存関係を挿入することはできませんでした。誰かが私がここで間違っていることを教えてもらえますか? Windows azure アプリケーション用に Spring.net DI を構成する別の方法はありますか?

構成エラーは発生しませんが、注入を試みたプロパティ オブジェクトが null のままであるため、依存関係が注入されていないことがわかります。

4

2 に答える 2

11

私の経験に基づくと、WorkerRole クラス (RoleEntryPoint を実装するクラス) には何も注入できません。これまでUnityで行ったこと (Azure 設定を挿入するのに役立つ Unity 用の独自のヘルパーも作成しました) は、Unity によって実行および構築された独自のインフラストラクチャを持っていることですが、ワーカー用のコードでそれを作成します。役割。

たとえば、RoleEntry ポイントの OnStart() メソッドで依存関係コンテナーを初期化し、そこで必要なものをすべて解決します。次に、Run() メソッドで、解決した依存関係のメソッドを呼び出します。

これは、私の RoleEntryPoint の実装の簡略化されたバージョンです。

public class WorkerRole : RoleEntryPoint
{
    private UnityServiceHost _serviceHost;
    private UnityContainer _container;

    public override void Run()
    {
        // This is a sample worker implementation. Replace with your logic.
        Trace.WriteLine("FIB.Worker entry point called", "Information");
        using (this._container = new UnityContainer())
        {
            this._container.LoadConfiguration();
            IWorker someWorker = this._container.Resolve<IWorker>();
            someWorker.Start();

            IWorker otherWorker = this._container.Resolve<IWorker>("otherWorker");
            otherWorker.Start();

            while (true)
            {
                // sleep 30 minutes. we don't really need to do anything here.
                Thread.Sleep(1800000);
                Trace.WriteLine("Working", "Information");
            }
        }
    }

    public override bool OnStart()
    {
        // Set the maximum number of concurrent connections 
        ServicePointManager.DefaultConnectionLimit = 12;

        // For information on handling configuration changes
        // see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.

        this.CreateServiceHost();

        return base.OnStart();
    }

    public override void OnStop()
    {
        this._serviceHost.Close(TimeSpan.FromSeconds(30));    
        base.OnStop();
    }

    private void CreateServiceHost()
    {
        this._serviceHost = new UnityServiceHost(typeof(MyService));

        var binding = new NetTcpBinding(SecurityMode.None);
        RoleInstanceEndpoint externalEndPoint =
            RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["ServiceEndpoint"];
        string endpoint = String.Format(
            "net.tcp://{0}/MyService", externalEndPoint.IPEndpoint);
        this._serviceHost.AddServiceEndpoint(typeof(IMyService), binding, endpoint);
        this._serviceHost.Open();
    }

ご覧のとおり、私自身のロジックは IWorker インターフェイスであり、必要な数の実装を持つことができ、それらを Run() メソッドで開始します。私がさらに行っていることは、Unity を使用して DI を介して完全に構成された WCF サービスを用意することです。ここに私の IWorker インターフェイスがあります:

public interface IWorker : IDisposable
{
    void Start();
    void Stop();
    void DoWork();
}

以上です。Unity コンテナーだけで、WorkerRole に「ハード」な依存関係はありません。そして、私の 2 つのワーカーには非常に複雑な DI があり、すべてがうまく機能しています。

WorkerRole.cs クラスに直接干渉できない理由は、独自のインフラストラクチャではなく、Windows Azure インフラストラクチャによってインスタンス化されているためです。それを受け入れて、インフラストラクチャを WorkerRole の適切なメソッド内に構築する必要があります。また、Run() メソッドを終了/中断/復帰/終了してはならないことを忘れないでください。これを行うと、Windows Azure インフラストラクチャにコードに問題があるというフラグが付けられ、ロールのリサイクルがトリガーされます。

お役に立てれば。

于 2012-05-20T09:33:25.980 に答える
0

これは古い質問であることは承知していますが、同じ学習曲線をたどっているので、メカニズムを理解するのに苦労している誰かのために私の発見を共有したいと思います.

ワーカー ロール クラスで DI にアクセスできない理由は、これが IIS の外部の OS の別のプロセスで実行されるためです。WebRoleクラスは、Windows サービスで実行されていると考えてください。

MVC Web サイトと WebRole クラスで少し実験を行いました。

public class WebRole : RoleEntryPoint
{
    public override void Run()
    {
        while (true)
        {
            Thread.Sleep(10000);
            WriteToLogFile("Web Role Run: run, Forest, RUN!");
        }
    }

    private static void WriteToLogFile(string text)
    {
        var file = new System.IO.StreamWriter("D:\\tmp\\webRole.txt", true); // might want to change the filename
        var message = string.Format("{0} | {1}", DateTime.UtcNow, text);

        file.WriteLine(message);
        file.Close();
    }
}

これにより、10 秒ごと (またはその程度) に新しい文字列がファイルに書き込まれます。次に、Azure サイトをデバッグ モードで開始します。サイトが Azure エミュレーターにデプロイされ、VS のデバッガーが開始されていることを確認します。サイトが実行されていることを確認し、WebRole が問題のファイルに書き込んでいることを確認します。

ここで、VS デバッガーを停止せずに IIS Express (完全なインストールで実行している場合は IIS) を停止します。あなたのウェブサイトのすべての操作は現在停止しています。ただし、一時ファイルを確認すると、プロセスはまだ実行されており、10 秒ごとに新しい行が追加されています。デバッガーを停止するまで。

したがって、Web アプリケーションのメモリにロードしたものはすべて IIS 内にあり、ワーカー ロール内では使用できません。また、DI やその他のサービスを最初から再構成する必要があります。

これが誰かが基本をよりよく理解するのに役立つことを願っています。

于 2013-06-25T10:35:37.477 に答える