2016-06-10 2 views
1

내 프로젝트에서 GeoJSON.NET 라이브러리를 사용하고 있습니다. 어떤 시점에서 데이터베이스의 기능을 업데이트해야합니다. 이 기능의 일부로 해당 기능을 데이터베이스에 저장하기 위해 해당 기능의 좌표에 액세스해야합니다.콘크리트 유형에 캐스트 인터페이스

public IGeometryObject Geometry { get; set; } 

는 "다각형", "서클", "포인트로 GeoJSON 사양에 따라 여러"모양 "이 존재 그러나 GitHub의에 소스 코드를 찾고 기능 클래스는 IGeometryObject으로 기하 속성이 있습니다 "등의 특정 모양이 GeoJSON.NET 프로젝트 내에 설정되었습니다.

내가 실제로 들어 와서 다양한 좌표에 액세스 할 수있는 구체적인 유형 내에 있습니다. 현재

나는이있다 : 나는 실제로 같은 다각형에 명시 적 낙심을하고 있어요 그래서 여기 내 코드에서

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

: 여기

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 클래스의 Coordinates 멤버에게 문의해야합니다. 필자는 비록 이것이 필연적으로 모범 사례는 아니지만 필자가 응용 프로그램에서 사용하고있는 유일한 "유형"유형이라는 점을 근거로이 작업을 수행하는 것이 안전하다는 것을 알고 있습니다. 그러나 미래에 다른 유형을 사용한다면 이것은 완전히 깨질 것입니다. 나는 타입 검사를 위해 "is or as"를 사용하여 구현할 수 있지만, 여전히 다운 캐스팅의 개념에서 벗어나지 않습니다.

제 질문은 이것에 대해 가장 좋은 방법은 무엇입니까? 나는 인터페이스와 그 모든 것을 멤버 및/또는 매개 변수로 사용하는 이유에 대해 읽었으며 명시 적 다운 캐스트를해야하는 것은 "보통"나쁜 습관이고 드문 경우를 제외하고 나쁜 디자인 패턴을 따른다. 그래서 나는 여기의 "드문 경우"에 빠지거나 이것에 대해 갈 수있는 더 좋은 방법이 있습니까?

답변

1

GeoJSON.NET API를 기반으로, 나는이 "드문 경우들"중 하나에 속한다고 생각합니다. 다음을 처리 할 수있는 몇 가지 옵션이 있습니다.

  1. 형상 특정 메소드로 발송되는 CreateFeature 메소드에 switch 문을 추가하십시오. 모양 별 기능을 모양 별 방법으로 이동하십시오 (아래 참조).
  2. 특정 유형 (예 : if (shape is Polygon) ProcessShape((Polygon)shape);)에 대해 유형을 확인하고 모양 별 메소드로 전달하는 경우 일련의 if..else를 만듭니다.
  3. visitor 패턴을 사용하여 모양 특정 메소드로 디스패치합니다 (GeoJSON.NET 라이브러리의 코드를 수정해야 함).옵션 1

샘플 코드 : 옵션 3

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

... 그리고, 그래서 GitHub의에 끌어 오기 요청을 제출 모두가 당신의 개선으로 혜택을 볼 수 있습니다!

+0

의견에 감사드립니다. 나는 그것을 매우 감사한다. 시간 제한으로 인해 모양 유형에 대한 선택의 폭이 너무 작아서 옵션 1을 고수 할 것입니다. – dvsoukup

+0

외부 API를 포크하고 변경하면 유지 관리가 훨씬 어려워 지므로 상당히 나쁜 생각입니다 (새로운 버전). 그 길로 가면 인터페이스에서 누락 된 함수를 실제로 추가 할 수 있습니다. GetGeoPosition() –

+0

GetGeoPosition()과 각 구체적인 유형의 설정이 여기에 핵심적인 부분이라고 생각합니다. 이 좌표를 얻는 데 과도한 엔지니어가 필요합니다. 감사! – dvsoukup

1

변경할 수없는 다른 사람 인터페이스의 내부 구현 세부 정보에 액세스해야한다고 결정했습니다.

그렇다면 미래 유지 관리 비용을 들여야합니다. 그렇습니다. 드문 경우 중 하나가 있습니다.

비용을 최소화하려면 게시 된 인터페이스에서 작동하는 도우미 클래스에서 모든 위험한 코드를 래핑하는 것이 좋습니다. 따라서 자신의 비즈니스 로직과 혼용하지 마십시오. 앞으로 변경해야 할 부분을 명확하게 파악할 수 있습니다.

+0

감사합니다. 당신은 기본적으로 @wablab이 예로 든 것을 말했습니다. 나는 이것이 드문 경우 중 하나라고 말하기 위해 또 다른 눈빛을 필요로했습니다. – dvsoukup

관련 문제