ヒント10:ジェネリックの概要
ジェネリックはVisual Studio 2005で最も話題になっている新しい言語機能の1つです。ジェネリックの説明でよく目にするのが、以前のバージョンの.NETではサポートされていなかったものであるということです。代表的な例がコレクションです。従来は、コレクションにあらゆる型のオブジェクトへの参照を格納しており、コレクション内の特定インデックスの値を取得するときにはキャストを実行していました。そのため、コンパイル時のタイプセーフが保証されず、キャスト時にボックス化とボックス化解除が生じるせいでパフォーマンスが低いという欠点がありました。
新しいVisual Studio 2005の名前空間Systems.Generic.Collectionsを使えば、コレクション作成時に受け付けるメンバの型を指定することができます。これにより、コンパイラは事前に宣言されている型のオブジェクトの追加のみを認めるようになります。その結果、コレクションから値を取得するときにキャストを実行する必要はなくなりました。
昨年秋にニュージャージー州で開かれたMSDN CodeCampで、Carl Franklinが行ったジェネリックの説明は、私がこれまでに聞いた中で最も短いものでした(www.DotNetRocks.comを参照)。Franklinによると、「ジェネリックは、内部型が異なる複数のクラスを簡易化する素晴らしい方法である」ということです。これを踏まえて、次のヒントに移ります。
ヒント11:本稿のスポットライト:ジェネリックを使ってリモーティングインターフェイスを簡易化する
先ほどのごく簡単な例には、1つのインターフェイスと1つのメソッドしか含まれていませんでした。もっと現実的なアプリケーションを考えてみましょう。モジュールが12あり、それぞれのモジュールに基本キーのデータを取得するメソッド(GetProduct
、GetAccount
、GetCostCenter
など)が含まれているとします。また、さまざまなモジュールに、別のカテゴリの関数があることも考えられます。このようなアプリケーションでは、ものすごい数のインターフェイスが必要になるのでしょうか?
Visual Studio 2005では、必ずしもそうなるとは限りません。Carl Franklinの「ジェネリックは内部型が異なる複数のクラスを簡易化する」という考えを応用すれば、1つの基本キーの整数(例えば、アカウントキーまたは製品キー)を受け取ってデータセット(例えば、アカウント結果または製品結果)を返すジェネリックインターフェイスを定義することができます。
using System; using System.Collections.Generic; using System.Text; using System.Data; namespace GenericInterfaces { public interface IRemoteGenericResultSet<T> { DataSet GetResults(int nID); } }
構文に注意してください。<T>
というプレースホルダは、これがジェネリックであることを示しています。実際の型を参照するときには、同様にして実際の型を指定します。次のコードは、このジェネリックインターフェイスを実装するオブジェクトへの参照を示します。
string cServer = "tcp://localhost:8228"; object oRemoteObject = Activator.GetObject( typeof(IRemoteGenericResultSet<DataSet>), cServer + "/GetCustomers"); IRemoteGenericResultSet<DataSet> oCustomer = oRemoteObject as IRemoteGenericResultSet<DataSet>; oCustomer.GetResults(111);
呼び出し側のプロシージャには特定のモジュールへの型参照は含まれていません。バックエンドオブジェクトの名前に関するリテラルがあるので、そのリテラルを文字列またはプロパティに簡単に挿入できます。
これは、ジェネリックを使ってプログラミングを簡易化する方法の一例です。ジェネリックの詳細は、「Baker's Dozen」シリーズの今後の記事で取り上げる予定です。
ヒント12:リモーティングオブジェクトファクトリを作成する
リモーティングを簡易化するもう1つの手段として、リモーティングの詳細を独立したクラスに分離する方法があります。リスト1に、リモーティングオブジェクトファクトリのコードを示します。アプリケーションから数多くのリモートオブジェクトにアクセスする場合は、このファクトリをインスタンス化し、ポート、サーバー、インターフェイス、および型参照に関するプロパティを目的のバックエンドオブジェクトのものに設定して、戻り値を適切なインターフェイスに渡します。
using System; using System.Collections.Generic; using System.Text; using System.Runtime ; using System.Runtime.Remoting; using System.Runtime.Remoting.Channels; using System.Runtime.Remoting.Channels.Tcp; namespace SimpleClientRemotingFactory { Public class RemotingFactory { private static int _nTCPPort; public int nTCPPort { get {return _nTCPPort ;} set {_nTCPPort = value;} } private static string _cTcpServer; public string cTcpServer { get {return _cTcpServer ;} set {_cTcpServer = value;} } private Type _tInterface; public Type tInterface { get {return _tInterface ;} set {_tInterface = value;} } private string _cRemoteObjectName; public string cRemoteObjectName { get { return _cRemoteObjectName; } set { _cRemoteObjectName = value; } } public RemotingFactory() { } public object GetRemoteInterfaceObject() { object oAccessObject = new object(); IChannel[] myIChannelArray = ChannelServices.RegisteredChannels; if(myIChannelArray.Length ==0) ChannelServices.RegisterChannel( new TcpClientChannel()); // activate back-end object oAccessObject = Activator.GetObject( this.tInterface, this.cTcpServer.ToString().Trim() + ":" + this.nTCPPort.ToString().Trim() + "/" + this.cRemoteObjectName ) ; return oAccessObject; } } }
ヒント13:リモーティングオブジェクトファクトリを使う
次に、ファクトリの簡単な使用例を示します。
using SimpleInterfaces; RemotingFactory oFactory = new RemotingFactory(); oFactory.nTCPPort = 8228; oFactory.cTcpServer = "tcp://localhost"; oFactory.cRemoteObjectName = "CustomerBzObject"; oFactory.tInterface = typeof(ICustomer); ICustomer oRemoteCustomer; oRemoteCustomer = (ICustomer)oFactory.GetRemoteInterfaceObject(); DataSet DsTemp= oRemoteCustomer.GetCustomer(111);
このコード例は、アドレスプロパティの設定方法を示しているだけで、実際のリモーティングコードは含まれていないことに注意してください。ここで重要なのは、リモーティングオブジェクトファクトリによってリモーティングの複雑さがすべて隠されていることです。
コメント
ここ1年間で、リモーティングに対する開発者の反応についていろいろなことを知りました。開発者の多くは、リモーティングは複雑だと思って敬遠しています。そこで私は、少しの手間をかければ、リモーティングに必要な処理をアプリケーションの他の部分から分離できるということを実証しようと思い立ちました。最初にわかったことは、リモーティングは少し複雑だが少し勉強すれば慣れるということでした。今では、私は可能なときにはいつでもリモーティングを使っています。
また、リモーティングを使っている開発者が多いという嬉しい驚きもありました。Indigoなどの新しいテクノロジーを待っている開発者もいますが、目下のアプリケーション問題を解決する方法を今すぐ知りたがっている開発者もたくさんいます。ちなみに、現在あるテクノロジの使い方を具体的に紹介することが、この「Baker's Dozen」シリーズの目標の1つです。
まとめ
リモーティングと、厳密な型指定による開発のメリットをお分かりいただけたでしょうか。今後、新しいMicrosoft開発テクノロジー(Indigo)が現れても、少なくとも当面の間はリモーティングが使われ続けるでしょう。
参考資料
リモーティングについて勉強したことのある人ならば、Ingo Rammerという名前に聞き覚えがあるでしょう。Ingo Rammerは、リモーティングの分野でトップクラスの専門家の1人です。Ingo Rammerの教えを受けたい人は、www.thinktecture.com/を参照してください。
リモーティングのソースコードの例は、MSDNオンラインのほかに、www.c-sharpcorner.comとwww.codeproject.comでも公開されています。www.TheServerSide.netでは、有益な記事が数多く紹介されています。www.Developer.comや、Microsoftのパブリックニュースサーバーのニュースグループにも、有益な情報が数多く掲載されています。