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();

问题是点和多边形形状 (IPointIPolygon) 都包裹在同一个类型 ( IFeature) 中,为此定义了扩展方法。扩展方法必须打开,IFeature因为我只能从一个IFeature到它的IGeometry,反之亦然。


问题:

虽然可以在运行时轻松检查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

使您的 IFeature 接口也通用:

IFeature<IPoint>
IFeature<IPolygon>

然后您可以对 IFeature 的内部类型设置一个约束。

于 2010-07-03T10:12:44.090 回答
1

根据定义,如果你有一个IFeature对象,那么它的Shape属性可以包含任何实现的类型的值IGeometry。如果您可以控制IFeature对象的实例化,那么您可以创建自己的泛型类来实现IFeature或从实现的框架类派生一个类,IFeature然后您可以轻松地约束Shape. 如果您无法控制这些对象的实例化,那么您可能会遇到运行时检查。

如果您碰巧使用的是 .NET 4.0,那么您可以使用代码协定。如果您的扩展方法对Shape.

于 2010-07-03T10:40:36.827 回答
1

我认为您无法在编译时使用 ArcObjects 的 IFeature 接口来实现此检查。

几何类型取决于从中加载要素的要素类的定义。直到运行时您才会知道这一点。

于 2010-07-30T16:18:26.593 回答
1

我认为添加仅适用于将功能指向 IFeature 接口的扩展方法是一个糟糕的设计。接口 IFeature 由所有类型的几何体(点、线和多边形)实现。这意味着扩展方法还应该设计为在扩展 IFeature 接口时支持所有类型的几何图形。显然不是这样的:-)

当您必须扩展 IFeature 时,请在运行时检查形状类型,如您所写。在我看来,这是解决您问题的最佳方法。

于 2011-09-22T08:40:33.100 回答
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 回答