操作方法:インスタンス コントロール プロバイダーの開発

以下は、カスタム インスタンス コントロール プロバイダーを作成する手順です。

  1. Class Library プロジェクトを作成します。

  2. Microsoft.ApplicationServer.StoreManagement への参照を追加します。さらに、System.Configuration アセンブリへの参照を追加し、このトピックのサンプル コードをコンパイルします。

  3. ソース ファイルの先頭に次のステートメントを追加します。

    using Microsoft.ApplicationServer.StoreManagement.Control;
    using Microsoft.ApplicationServer.StoreManagement.Control;
    using System.Data.SqlClient;
    using System.Collections.Specialized;
    using System.Threading;
    using System.Data;
    
  4. InstanceControlProvider クラスから、インスタンス コントロール プロバイダー用のクラスを作成します。

        public class MySqlInstanceControlProvider : InstanceControlProvider
        {
        }
    
  5. Initialize メソッドを実装します。このメソッドは、構成ファイルで指定された構成情報に対応するプロパティ バッグを受け付けます。このプロパティ バッグのデータはプロバイダーの作成に使用されます。Initialize メソッドは CreateInstanceControl メソッドまたは UniqueProviderIdentifier メソッドよりも前に呼び出されます。

    ヒント

    リモートのシナリオでは、名前と値のコレクションに "EnableServiceModelMetadata" という名前の項目が含まれます。プロバイダーは、base.Initialize メソッドを呼び出す前に、このパラメーターを無視して削除するよう選択することができます。このプロパティは通常、Microsoft.Web.Administration.ServerManager オブジェクトについて SetMetadata("ServiceModel", true) を呼び出すかどうかを決定するために使用します。

    
            string ConnectionString { get; set; }
    
            public override void Initialize(string name, NameValueCollection config)
            {
    
                this.ConnectionString = config["connectionString"];
    
                // Initialize the base class
                base.Initialize(name, config);
            }
    
  6. InstanceControlProvider クラスの CreateInstanceControl メソッドを実装し、カスタム オブジェクトである InstanceControl オブジェクトを返します。このオブジェクトは、クライアントが CommandSend オブジェクトまたは CommandReceive オブジェクトにアクセスするために使用します。

            public override InstanceControl CreateInstanceControl()
            {
                SqlConnectionStringBuilder connectionStringBuilder = new SqlConnectionStringBuilder(this.ConnectionString);
                connectionStringBuilder.AsynchronousProcessing = true;
                return new MySqlInstanceControl(connectionStringBuilder.ConnectionString);
            }
    

    ヒント

    MySqlInstanceControl 型の実装については、次のセクションを参照してください。

  7. UniqueProviderIdentifier メソッドを実装します。このメソッドが返す一意のプロバイダー ID を使用して、異なるプロバイダー オブジェクトが、基になる同一のストアに解決されるかどうかを判断します。

            string UniqueStoreIdentifier { get; set; }
    
            public override string UniqueProviderIdentifier()
            {   
                this.UniqueStoreIdentifier = GetUniqueStoreIdentifier(this.ConnectionString); 
                return this.UniqueStoreIdentifier;
            }
    
            private string GetUniqueStoreIdentifier(string connectionString)
            {
                using (SqlConnection connection = new SqlConnection(connectionString))
                {
                    using (SqlCommand command = new SqlCommand())
                    {
                        command.CommandType = System.Data.CommandType.Text;
                        command.CommandText = "SELECT TOP (1) [StoreIdentifier] FROM [Microsoft.ApplicationServer.DurableInstancing].[StoreVersion]";
                        command.Connection = connection;
    
                        command.Connection.Open();
    
                        Guid identifier = (Guid)command.ExecuteScalar();
                        return identifier.ToString();
                    }
                }
            }
    

InstanceControl の実装

以下は、カスタム型である InstanceControl 型を作成する手順です。

  1. InstanceControl クラスから派生するクラスを作成します。

        public class MySqlInstanceControl : InstanceControl
        {
            readonly string connectionString;
             public MySqlInstanceControl(string connectionString)
             {
                 this.connectionString = connectionString;
             }
        }
    
  2. CommandReceive プロパティを実装します。CommandReceive プロパティの Get アクセサー メソッドは、CommandReceive オブジェクトを返します。クライアントはこのオブジェクトについてメソッドを呼び出し、コマンド キューからのコマンドを非同期で受信します。

            MySqlCommandReceive commandReceive;
            public override CommandReceive CommandReceive
            {
                get 
                {
                    if (this.commandReceive == null)
                    {
                        MySqlCommandReceive tmp = new MySqlCommandReceive(this.connectionString);
                        Interlocked.CompareExchange(ref this.commandReceive, tmp, null);
                    }
                    return this.commandReceive;
                }
            }
    
  3. CommandSend プロパティを実装し、Get アクセサー メソッドによって、カスタム オブジェクトである CommandSend オブジェクトを返します。CommandSend プロパティの Get メソッドは、CommandSend オブジェクトを返します。クライアントはこのオブジェクトのメソッドを呼び出して、非同期でコマンドをコマンド キューに送信します。

            MySqlCommandSend commandSend;
            public override CommandSend CommandSend
            {
                get
                {
                    if (this.commandSend == null)
                    {
                        MySqlCommandSend tmp = new MySqlCommandSend(this.connectionString);
                        Interlocked.CompareExchange(ref this.commandSend, tmp, null);
                        return this.commandSend;
                    }
                    return this.CommandSend;
                }
            }
    

    クライアントはこれら 2 つのオブジェクトを使用して、コマンド キューにコマンドを送信 (コマンド キューへコマンドを登録) したり、コマンド キューからコマンドを受信 (コマンド キューからコマンドを削除) したりします。たとえば、インスタンス制御コマンドレットが CommandSend オブジェクトを使用してコマンド キューにコマンドを登録したり、Workflow Management Service (WMS) が CommandReceive オブジェクトを使用してコマンド キューからコマンドを削除したりします。Remove-ASAppServiceInstance コマンドレットを実行する場合など、場合によっては、ストア自体がコマンドを処理してインスタンス ストアからインスタンスを削除します。

    ヒント

    MySqlCommandSend 型および MySqlCommandReceive 型の実装については、以下のセクションを参照してください。

CommandSend の実装

カスタム型である CommandSend 型を作成するには

  • CommandSend クラスから派生するクラスを作成し、BeginTrySend メソッドおよび EndTrySend メソッドを実装します。

        public class MySqlCommandSend : CommandSend
        {
            readonly string connectionString;
    
            public MySqlCommandSend(string connectionString)
            {
                this.connectionString = connectionString;
            }
    
            public override IAsyncResult BeginSend(InstanceCommand command, TimeSpan timeout, AsyncCallback callback, object state)
            {
                throw new NotImplementedException();
            }
    
            public override void EndSend(IAsyncResult result)
            {
                throw new NotImplementedException();
            }
        }
    

CommandReceive の実装

カスタム型である CommandReceive 型を作成するには

  • CommandReceive クラスから派生するクラスを作成し、BeginTryReceive メソッドおよび EndTryReceive メソッドを実装します。

        public class MySqlCommandReceive : CommandReceive
        {
            readonly string connectionString;
    
            Queue<MySqlReceivedInstanceCommand> receivedInstanceCommands;
    
            public MySqlCommandReceive(string connectionString)
            {
                this.connectionString = connectionString;
                this.receivedInstanceCommands = new Queue<MySqlReceivedInstanceCommand>();          
            }
    
            public override IAsyncResult BeginTryReceive(TimeSpan timeout, AsyncCallback callback, object state)
            {
                throw new NotImplementedException();
            }
    
            public override bool EndTryReceive(IAsyncResult result, out ReceivedInstanceCommand command)
            {
                throw new NotImplementedException();
            }
        }
    

    ヒント

    MySqlReceivedInstanceCommand クラスの実装については、以下のセクションを参照してください。

ReceivedInstanceCommand の実装

カスタム型である ReceivedInstanceCommand 型を作成するには

  • ReceivedInstanceCommand クラスから派生するクラスを作成し、InstanceCommandContext プロパティを実装します。

        class MySqlReceivedInstanceCommand : ReceivedInstanceCommand
        {
            long commandId;
            MySqlCommandReceive receiver;
            MySqlInstanceCommandContext context;
    
            internal MySqlReceivedInstanceCommand(long commandId,
                 Guid instanceId, Microsoft.ApplicationServer.StoreManagement.Control.CommandType commandType, IDictionary<string, string> serviceIdentifier, TimeSpan timeout,
                MySqlCommandReceive receiver) : base()
            {
                this.commandId = commandId;
                base.CommandType = commandType;
                base.InstanceId = instanceId;
                base.ServiceIdentifier = serviceIdentifier;
                //this.CommandTimeout = new TimeoutHelper(timeout, true);
                this.receiver = receiver;
                this.context = new MySqlInstanceCommandContext(this);
            }
            public override InstanceCommandContext InstanceCommandContext
            {
                get
                {
                    return this.context;
                }
            }
        }
    

    ヒント

    MySqlInstanceCommandContext 型の実装については、以下のセクションを参照してください。

InstanceCommandContext の実装

カスタム型である InstanceCommandContext 型を作成するには

  • InstanceCommandContext クラスから派生するクラスを作成し、BeginComplete メソッド、EndComplete メソッド、BeginAbandon メソッド、および EndAbandon メソッドを実装します。

    クライアントは、InstanceCommandContext オブジェクトについて BeginComplete メソッドを呼び出し、コマンドの実行が成功したことを通知します。その後、コントロール プロバイダーはコマンド キューからコマンドを削除します。WMS は、コマンドの実行が成功した場合にこのメソッドを呼び出します。

    クライアントは、InstanceCommandContext オブジェクトについて BeginAbandon メソッドを呼び出し、コマンドの実行が失敗したことを通知します。コマンドに関して何を実行するかはインスタンス コントロール プロバイダーが決定します。たとえば、コントロール プロバイダーは、コマンド キューからコマンドを削除する前に、一定回数コマンドを再試行できます。WMS は、コマンドの実行が失敗した場合にこのメソッドを呼び出します。

        class MySqlInstanceCommandContext : InstanceCommandContext
        {
            MySqlReceivedInstanceCommand command;
    
            internal MySqlInstanceCommandContext(MySqlReceivedInstanceCommand command)
            {
                this.command = command;
            }
    
            public override IAsyncResult BeginAbandon(Exception exception, TimeSpan timeout, AsyncCallback callback, object state)
            {
                throw new NotImplementedException();
            }
    
            public override IAsyncResult BeginComplete(TimeSpan timeout, AsyncCallback callback, object state)
            {
                throw new NotImplementedException();
            }
    
            public override void EndAbandon(IAsyncResult result)
            {
                throw new NotImplementedException();
            }
    
            public override void EndComplete(IAsyncResult result)
            {
                throw new NotImplementedException();
            }
        }
    

関連項目

概念

操作方法:インスタンス ストア プロバイダーの開発
操作方法: インスタンス クエリ プロバイダーの開発
操作方法: インスタンス ストア プロバイダー、インスタンス クエリ プロバイダー、およびインスタンス コントロール プロバイダーの構成
インスタンス ストア、クエリ、およびコントロール プロバイダー

  2011-12-05