2013-02-20 2 views
5

내 C# pojects에 대해 NHibernate를 사용하고 있으므로 여러 모델 클래스가 있습니다.C#에서 가상 메서드를 호출하는 대신

using System; 

namespace TestProject.Model 
{ 
    public class Room 
    { 
     public virtual int Id { get; set; } 
     public virtual string UniqueID { get; set; } 
     public virtual int RoomID { get; set; } 
     public virtual float Area { get; set; } 

    } 
} 

NHibernate에 지금까지 잘 작동으로 이러한 개체를 매핑 :

는 다음과 같은 예를 가정 할 수 있습니다. 이제 새 Room 객체를 생성하고 데이터베이스에 저장하려고합니다. 각 멤버를 seperatly로 설정하지 않으려면 모델 클래스에 새 생성자를 추가합니다. 이 잘못된 이유

"ConstructorShouldNotCallVirtualMethodsRule" 
This rule warns the developer if any virtual methods are called in the constructor of a non-sealed type. The problem is that if a derived class overrides the method then that method will be called before the derived constructor has had a chance to run. This makes the code quite fragile. 

This page도 설명하고 또한 그것을 이해 :의 FxCop 내 코드를 분석

public RoomProperty() 
{ 

} 


public RoomProperty(int pRoomId, int pArea) 
{ 
     UniqueID = Guid.NewGuid().ToString(); 
     RoomID = pRoomId; 
     Area = pArea; 
} 

다음 내게 말하길 : 가상 구성원 아래 나는 물품. 그러나 나는 문제를 해결하는 방법을 자극하지 않는다. 내가 NHibernate에 초기화 실패 becaue 내 aplication을 시작하지 못할 표준 생성자 호출 후

나는 모든 생성자를 지우고 다음과 같은 방법을 추가

...

public void SetRoomPropertyData(int pRoomId, int pArea) 
     { 
      UniqueID = Guid.NewGuid().ToString(); 
      RoomID = pRoomId; 
      Area = pArea; 

     } 

는 .... 데이터를 설정합니다. 그것은 말합니다 :

그러나이 방법을 가상으로 설정하는 것은 생성자에서 가상 멤버를 설정했을 때와 같은 실수입니다. 이러한 실수 (위반)는 어떻게 피할 수 있습니까?

+0

시공시 속성이 아닌 필드에 값을 설정하지 않는 이유는 무엇입니까? –

+0

@ voroninp NHibernate가있는 필드에 쉽게 액세스 할 수 없습니다 – Andrey

+0

내 모델에는 실제로 약 10 명의 멤버가 있으므로 qiet iften이라는 새 룸 개체를 만듭니다. 나는 각 속성을 seperatly로 설정하고 싶지 않다. – Metalhead89

답변

4

문제는 가상 세트에 있습니다. 기본 클래스 생성자의 가상 속성에 값을 전달하면 기본 집합 대신 재정의 된 집합이 사용됩니다. 재정의 집합이 파생 클래스의 데이터를 사용하는 경우 파생 클래스의 생성자가 아직 완료되지 않았으므로 문제가 발생합니다.

확실한 경우 모든 하위 클래스는 재정의 된 집합에서 해당 상태의 데이터를 사용하지 않으므로 기본 클래스 생성자에서 가상 속성을 초기화 할 수 있습니다. 문서에 적절한 경고를 추가하는 것을 고려하십시오.

가능한 경우 각 속성에 대한 백킹 필드를 만들어 기본 클래스 생성자에서 사용하십시오.

속성 초기화를 파생 클래스로 연기 할 수도 있습니다. 이를 달성하기 위해 파생 클래스의 생성자에서 호출하는 기본 클래스에 초기화 메서드를 만듭니다.

1

나는 일에 다음 중 하나를 예상 :

  1. 가 (한 NHibernate에 그것을 지원하는 선호)의 속성이 아닌 가상합니다.
  2. 자동 구현 속성에서 명시적인 배경 필드가있는 속성으로 변경하고 속성을 설정하는 대신 생성자에서 필드를 설정하십시오.
  3. 먼저 개체를 구성하는 정적 Create 메서드를 만든 다음 구성된 개체를 반환하기 전에 속성에 값을 설정합니다.

편집 : 옵션 # 3이 분명하지 않은 것으로 보입니다.

public class Room 
{ 
    public virtual int Id { get; set; } 
    public virtual string UniqueID { get; set; } 
    public virtual int RoomID { get; set; } 
    public virtual float Area { get; set; } 

    public static Room Create(int roomId, int area) 
    { 
     Room room = new Room(); 
     room.UniqueID = Guid.NewGuid().ToString(); 
     room.RoomID = roomId; 
     room.Area = area; 
     return room; 
    } 
} 
+0

NHibernate는 비 가상 속성을 지원하지 않습니다. 그리고 또한 메서드를 정적으로 설정할 수 없기 때문에 속성도 정적이되어야합니다. (이 메서드가 작동하면 shure도 아닙니다) – Metalhead89

+0

옵션 3을 명확하게하기 위해 게시물을 편집했습니다. 메서드는 정적이지만 속성은 그렇지 않습니다. –

+0

옵션 3은 생성자를 보호하는 경우에 더 효과적이므로 'Room'인스턴스를 생성하는 유일한 방법은 static 메소드를 사용하는 것입니다. –

관련 문제