操作方法:インスタンス コントロール プロバイダーの開発
以下は、カスタム インスタンス コントロール プロバイダーを作成する手順です。
Class Library プロジェクトを作成します。
Microsoft.ApplicationServer.StoreManagement への参照を追加します。さらに、System.Configuration アセンブリへの参照を追加し、このトピックのサンプル コードをコンパイルします。
ソース ファイルの先頭に次のステートメントを追加します。
using Microsoft.ApplicationServer.StoreManagement.Control; using Microsoft.ApplicationServer.StoreManagement.Control; using System.Data.SqlClient; using System.Collections.Specialized; using System.Threading; using System.Data;
InstanceControlProvider クラスから、インスタンス コントロール プロバイダー用のクラスを作成します。
public class MySqlInstanceControlProvider : InstanceControlProvider { }
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); }
InstanceControlProvider クラスの CreateInstanceControl メソッドを実装し、カスタム オブジェクトである InstanceControl オブジェクトを返します。このオブジェクトは、クライアントが CommandSend オブジェクトまたは CommandReceive オブジェクトにアクセスするために使用します。
public override InstanceControl CreateInstanceControl() { SqlConnectionStringBuilder connectionStringBuilder = new SqlConnectionStringBuilder(this.ConnectionString); connectionStringBuilder.AsynchronousProcessing = true; return new MySqlInstanceControl(connectionStringBuilder.ConnectionString); }
ヒント
MySqlInstanceControl 型の実装については、次のセクションを参照してください。
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 型を作成する手順です。
InstanceControl クラスから派生するクラスを作成します。
public class MySqlInstanceControl : InstanceControl { readonly string connectionString; public MySqlInstanceControl(string connectionString) { this.connectionString = connectionString; } }
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; } }
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