C#ATIA

↑タイトル詐欺 主にFusion360API 偶にCATIA V5 VBA(絶賛ネタ切れ中)

CATIAのコレクションクラスで、お手軽にLinqを使いたい

こちらの最後の方に記載した
Viewに基準線を入れる2 - C#ATIA
ToEnumerable<T>のようなジェネリックメソッドを真剣に考えてみました。


結局のところ、CATIAのクラス内からコレクションクラスだと言う事を
判断しなければならないのですが、単純にGetType()を使用しても
'System.__ComObject'と返って来てしまい、何が何だかわからないです。
(CATIAに限らず、DotNetExcel等を扱う際も同じなのではないだろうか?)

結果的に

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名を表示します。
f:id:kandennti:20150519193528p:plain
このような場合、"パーツボディ-""ボディ-.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クラスは排除出来ています。
今後は使っていきますよ。