こちらの最後の方に記載した
Viewに基準線を入れる2 - C#ATIA
ToEnumerable<T>のようなジェネリックメソッドを真剣に考えてみました。
結局のところ、CATIAのクラス内からコレクションクラスだと言う事を
判断しなければならないのですが、単純にGetType()を使用しても
'System.__ComObject'と返って来てしまい、何が何だかわからないです。
(CATIAに限らず、DotNetでExcel等を扱う際も同じなのではないだろうか?)
結果的に
Information.TypeName(Hoge)
のような書き方を行うことになってしまうのですが、これではイチイチ
オブジェクト名からコレクションクラスか?を判断しなければならず
ちっともジェネリックメソッドにはならないです。
オートメーションマニュアルを良く見ると、CATIAのコレクションは
'INFITF.Collection'クラスから派生されており、参照設定されていれば
DotNetでも認識されていました。(もっと早く気が付くべき・・・)
しかもありがたいことに、少し挙動の異なるSelectionクラスは継承されて
いない為、これを利用した拡張メソッドがこんな感じで書けます。
(このBlogは、横長だと見難い為改行しまくっています)
//cs static class CatExtension { public static IEnumerable<T> ToEnumerable<T> (this INFITF.Collection coll) { foreach (T item in coll) { yield return item; } } }
たったこれだけを書く為に、何時間費やしたのだろう・・・。
このジェネリックメソッドを利用したサンプルです。
Partファイル内のBodyでブール演算されていない(直接Treeにぶら下がっている)
Body名を表示します。
このような場合、"パーツボディ-""ボディ-.2""ボディ-.3"を拾い出します。
では、ソースコードです。(今回はみんな大好きコンソールアプリ)
//cs namespace Part_Body_Count { using System; using System.Collections.Generic; using System.Linq; using MECMOD; using System.Runtime.InteropServices; class Program { static void Main(string[] args) { var PartTest = new test(); PartTest.Execute(); } } class test { public void Execute() { var catia = (INFITF.Application)Marshal .GetActiveObject("CATIA.Application"); PartDocument PartDoc = (PartDocument)catia.ActiveDocument; var Bodies = PartDoc.Part.Bodies; foreach (var body in Bodies//① .ToEnumerable<Body>()//② .Where(i => i.InBooleanOperation == false)) {//③ Console.WriteLine(body.get_Name()); } Console.ReadLine(); } } }
改行していますが①~③が一行です。
②:先程作成した拡張メソッドでコレクション内の型を<Body>で指定しています。
③:'InBooleanOperation'メソッドで、ブール演算の可否を判断しています。
物凄く悩みましたが、CATIAのコレクションクラスで簡単にLinqが使用できるように
なりとても便利。 しかもネックのSelectionクラスは排除出来ています。
今後は使っていきますよ。