3

初期状況:

私は独自のフレームワーク ( ESRIArcGIS Engine ) を使用しており、これをいくつかの新しい機能で拡張したいと考えています。このために、C# で拡張メソッドを使用することにしました。

この質問に関連するフレームワーク API の部分を以下に示します。

    +------------------------+                   IGeometry
    |  IFeature <interface>  |                   <interface>
    +------------------------+                       ^
    |  +Shape: IGeometry     |                       |
    +------------------------+             +---------+---------+
                                           |                   |
                                        IPoint              IPolygon
                                        <interface>         <interface>

私がしたいこと:

IFeature以下を可能にする拡張メソッドを作成したいと思います。

IFeature featureWithPointShape   = ...,
         featureWithPolygonShape = ...;

// this should work:
featureWithPointShape.DoSomethingWithPointFeature();

// this would ideally raise a compile-time error:
featureWithPolygonShape.DoSomethingWithPointFeature();

問題は、ポイント シェイプとポリゴン シェイプ (IPointおよび) の両方が、拡張メソッドが定義されIPolygonている同じタイプ ( ) にラップされていることです。からその に向かってのみ取得できますが、その逆はできないためIFeature、拡張メソッドをオンにする必要があります。IFeatureIFeatureIGeometry


質問:

IFeatureオブジェクトの型はShape実行時に簡単にチェックできますが (以下のコード例を参照)、コンパイル時にこの型チェックを行うにはどうすればよいでしょうか?

public static void DoSomethingWithPointFeature(this IFeature feature)
{
    if (!(feature.Shape is IPoint))
    {
        throw new NotSupportedException("Method accepts only point features!");
    }
    ...  // (do something useful here)
}

IFeature(たとえばFeatureWithShape<IPoint>、このラッパー型で拡張メソッドを定義し、何らかの方法ですべてのIFeatureオブジェクトをこのラッパー型に変換するなど、一般的なラッパー型を使用する方法はありますか?)

4

5 に答える 5

1

ArcObjects の IFeature インターフェイスを使用して、コンパイル時にこのチェックを実行できるとは思いません。

ジオメトリ タイプは、フィーチャの読み込み元のフィーチャクラスの定義によって異なります。これは実行時までわかりません。

于 2010-07-30T16:18:26.593 に答える
1

機能を IFeature インターフェイスにポイントするのにのみ適した拡張メソッドを追加するのは悪い設計だと思います。インターフェイス IFeature は、すべてのタイプのジオメトリ (ポイント、ライン、ポリゴン) によって実装されます。これは、IFeature インターフェイスを拡張するときに、すべてのタイプのジオメトリをサポートするように拡張メソッドを設計する必要があることを意味します。これは明らかにそうではありません:-)

IFeature を拡張する必要がある場合は、実行時に形状タイプを確認してください。私の目には、それがあなたの問題に対する最善の解決策です。

于 2011-09-22T08:40:33.100 に答える
1

IFeature インターフェイスもジェネリックにします。

IFeature<IPoint>
IFeature<IPolygon>

次に、IFeature の内部型に制約を設定できます。

于 2010-07-03T10:12:44.090 に答える
1

定義により、IFeatureオブジェクトがある場合、そのShapeプロパティには を実装する任意の型の値を含めることができますIGeometryIFeatureオブジェクトのインスタンス化を管理している場合は、実装する独自のジェネリック クラスを作成するIFeatureか、実装するフレームワーク クラスからクラスを派生させてIFeature、 の型を簡単に制約できますShape。これらのオブジェクトのインスタンス化を制御できない場合は、おそらくランタイム チェックで行き詰っています。

たまたま .NET 4.0 を使用している場合は、コード コントラクトを使用できます。静的チェッカーは、拡張メソッドに の型に関する前提条件がある場合、コンパイル時に警告を出しますShape

于 2010-07-03T10:40:36.827 に答える
0

特に私は生計を立てるために ArcObjects を使用してプログラミングする必要があるため、興味深い質問です。

編集、警告: このアプローチは機能しません。実行時に失敗します。恥ずかしいのでここに置いておきます。

Sebastian PR Gingter のインターフェイスの継承に関する提案を取り入れて実行し、IFeatureOf<T>継承するインターフェイスを定義しましたIFeature。この新しいインターフェイスの唯一の利点は、機能を宣言するときに情報を追加することです。

ただし、ポイント フィーチャを扱っていることが事前にわかっている場合は、これらのフィーチャを として宣言しIFeatureOf<IPoint>、ポイント ジオメトリを含むフィーチャを予期する関数に供給することができます。

もちろん、ポリゴン フィーチャクラスのフィーチャを として宣言することもできvar notReallyAPointFeature = (IFeatureOf<IPoint>)myPolygonFeature;ますが、事前にフィーチャ タイプを知っていてIFeatureOF<>、それを制約するために使用する場合、それを特殊な関数に渡すと、コンパイル時にエラーが発生します。

以下の小さな例:

using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Geodatabase;

class Program
{
    public interface IFeatureOf<T> : IFeature { };

    public static void AcceptsAllFeatures(IFeature feature) {
        //do something, not caring about geometry type...
        return;
    }

    public static void AcceptsOnlyPointFeatures(IFeatureOf<IPoint> pointFeature) {
        IPoint pointGeometry = (IPoint)pointFeature.Shape; //constraint guarantees this is OK
        //do something with pointGeometry
        return;
    }

    static void Main(string[] args)
    {
        IFeature pointFeature = new FeatureClass(); //this is where you would read in a feature from your data set
        IFeature polylineFeature = new FeatureClass();
        var constainedPointFeature = (IFeatureOf<IPoint>)pointFeature;
        var constrainedPolylineFeature = (IFeatureOf<IPolyline>)polylineFeature;

        AcceptsAllFeatures(constainedPointFeature);             //OK
        AcceptsAllFeatures(constrainedPolylineFeature);         //OK
        AcceptsAllFeatures(pointFeature);                       //OK
        AcceptsAllFeatures(polylineFeature);                    //OK

        AcceptsOnlyPointFeatures(constainedPointFeature);       //OK

        AcceptsOnlyPointFeatures(constrainedPolylineFeature);   //Compile-time error: IFeatureOf<IPolyline> != IFeatureOf<IPoint>
        AcceptsOnlyPointFeatures(pointFeature);                 //Compile-time error: IFeature != IFeatureOf<something>
        AcceptsOnlyPointFeatures(polylineFeature);              //Compile-time error: IFeature != IFeatureOf<something>
    }
}
于 2010-07-03T14:51:36.613 に答える