簡體   English   中英

將界面投射到混凝土類型

[英]Cast interface to concrete type

我在我的項目中使用GeoJSON.NET庫。 在某些時候,我需要更新數據庫中的功能。 作為其一部分,我需要訪問所述要素的坐標,以便將該信息也存儲在數據庫中。 但是,查看GitHub上的源代碼,Feature類具有Geometry屬性作為IGeometryObject:

 public IGeometryObject Geometry { get; set; }

根據GeoJSON規范,存在多個“形狀”,例如“多邊形”,“圓形”,“點”等。這些特定形狀已在GeoJSON.NET項目中設置。

我可以在這些具體類型中進行實際挖掘並訪問各種坐標。

目前我有這個:

    public int CreateFeature(Feature feature)
    {
        int featureId = 0;
        var coordinatesDt = new DataTable();
        coordinatesDt.Columns.Add("Latitude");
        coordinatesDt.Columns.Add("Longitude");

        //we are loading a datatable with the coordinates.  This gets passed to a SQL server stored procedure as a single parameters to insert
        //all the nodes.
        LineString lineString = ((Polygon)feature.Geometry).Coordinates[0];
        foreach (var coordinate in lineString.Coordinates)
        {
            var row = coordinatesDt.NewRow();
            row["Latitude"] = ((GeographicPosition)coordinate).Latitude;
            row["Longitude"] = ((GeographicPosition) coordinate).Longitude;
            coordinatesDt.Rows.Add(row);
        }


        using (SqlConnection conn = new SqlConnection(_smmConnectionString))
        using (SqlCommand cmd = new SqlCommand("dbo.MyProc", conn))
        {
            //set up params, set up TVP and execute...
        }
        return featureId;
}

這是Polygon類的摘錄:

public List<LineString> Coordinates { get; set; }

因此,在我的代碼中,實際上我正在對Polygon進行顯式下調,因為我需要獲取Polygon類的Coordinates成員。 我知道僅基於這些是我在應用程序中使用的形狀的唯一“類型”,就可以安全地這樣做,即使我知道這不一定是最佳實踐。 但是,將來如果我們使用其他類型,則將完全中斷。 我可以使用“ is或as”進行類型檢查,但這仍然並沒有使我擺脫必須垂頭喪氣的想法。

所以我的問題是最好的方法是什么? 我已經讀過有關為什么使用接口以及將其全部用作成員和/或參數的信息,並且必須進行顯式的向下轉換是“通常”的不正確做法,並且遵循錯誤的設計模式……(除了極少數情況)。 那么,我是否屬於“稀有案例”呢?還是有更好的方法來解決這個問題?

因此,您已經決定需要訪問無法更改的其他人接口的內部實現細節。

然后,您別無選擇,只能承擔將來的維護費用。 是的,您有其中一種罕見的情況。

為了最大程度地降低成本,我強烈建議您將所有危險代碼包裝在可運行於已發布界面上的幫助程序類中,以便不要將其與自己的業務邏輯混合在一起,並且清楚地看到將來需要進行更改的地方。

基於GeoJSON.NET API,我認為您確實屬於這些“稀有案例”之一。 您可以選擇幾種方法來處理此問題:

  1. 在您的CreateFeature方法中添加一個switch語句,該語句將分派到特定於形狀的方法。 將特定於形狀的功能移至特定於形狀的方法中(請參見下文)。
  2. 創建一系列if..else if來進行特定類型的類型檢查(例如, if (shape is Polygon) ProcessShape((Polygon)shape); ),然后分派到特定於形狀的方法。
  3. 使用訪問者模式可以調度到特定於形狀的方法(盡管這需要您修改GeoJSON.NET庫的代碼)。

選項1的示例代碼

switch (shape.Type)
{
    case GeoJSONObjectType.Polygon:
        ProcessShape((Polygon)shape);
        break;
    // additional shape support here...
}

選項3的示例代碼

// Add an AcceptVisitor method to the IGeometryObject interface:
public interface IGeometryObject
{
    GeoJSONObjectType Type { get; }
    void AcceptVisitor(IShapeProcessor visitor);
}
// Update each concrete shape class to include the new AcceptVisitor method:
public void AcceptVisitor(IShapeProcessor visitor)
{
    visitor.ProcessShape(this);
}
// Add an IShapeProcessor interface to the GeoJSON.NET project:
public interface IShapeProcessor
{
    void ProcessShape(Polygon shape);
    void ProcessShape(MultiPoint shape);
    void ProcessShape(LineString shape);
    // ...additional shape support...
}
// Update your existing class to implement the IShapeProcessor interface,
// and then change your code to do something like:
feature.Geometry.AcceptVisitor(this);

...如果您選擇選項3,請在GitHub上提交拉取請求,以便每個人都可以從您的改進中受益!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM