이것에 대해 별도의 클래스를 만들어야합니까?
-
11-09-2019 - |
문제
내 프로젝트에는 많은 클래스가 포함되어 있으며 그 중 많은 수업이 XML 파일로 설명 될 수 있습니다. 걱정하지 마십시오. XML의 논리 나 구현이 아닙니다. 그것은 게임이며, 예를 들어 게임 타일은 XML, 이미지 파일, 애니메이션 프레임 등으로 정의 될 수 있다는 것입니다.
나는 다음과 같은 것처럼 보이는 많은 기능을 갖게 될 것입니다.
public static Foo FromXml(ref XmlTextReader reader) { ... }
문제는 다음과 같습니다. 이러한 기능이 자체 일치 클래스에 포함되면 위의 기능은 foo.foomxml입니다. 아니면 파일에서 내용을 읽기 위해 별도의 클래스를 만들어야합니까? 여기에는 경쟁하는 두 가지 일반적인 지침이있는 것 같습니다.
- 수업은 한 가지에 대한 모든 것을 알아야합니다.
- 수업에는 변경해야 할 이유가 하나만 있어야합니다.
우선, "이유"가 상당히 모호하기 때문에 두 번째를 이해하지 못합니다. 첫 번째 지침은 각 독자를 관련 클래스에 넣는 것을 제안합니다. 두 번째는 XML 파일을 읽는 데 전념하는 한 클래스를 만들라고 말합니다. 그러나 장단점은 논쟁의 여지가 있습니다. 한편으로, 각 수업에는 자체 독자가 포함될 수 있으므로 수십 개의 수업이 참조되지 않습니다. 반면에 모든 클래스에는 System.xml이 포함되어야하며 XML 형식을 변경하면 여러 파일에서 상황이 변경 될 수 있지만 너무 나쁘다고 생각합니다).
나는 가장 중요한 규칙은 "당신의 두뇌 사용"이라는 것을 알고 있으며 "올바른"솔루션과 같은 것은 없으며, 좋은 것만이 많고 일하는 것만이 없습니다. 그렇다면 더 읽기 쉽거나 더 잘 유지할 수 있다고 생각하십니까?
편집 : 명확히하기 위해, 수업은 완전히 관련이 없을 수 있습니다. 게임이기 때문에 스프라이트 애니메이션 클래스 일 수 있으며 적의 행동을 정의 할 수 있으며 맵 레이아웃 또는 속성을 정의 할 수 있습니다. 따라서 상속은 이것과 아무 관련이 없습니다.
해결책
Fromxml (...) 함수가 동일합니까? 그들이 코드 복제가 없기 때문에 그것들을 일반적인 라이브러리 영역에 넣을 것이라고 가정 할 때, 나는 그것을 일반적인 라이브러리 영역에 넣을 것이라고 가정합니다. 코드도 여전히 깔끔해야합니다
SomeObject o = (SomeObject)Foo.FromXml(reader);
편집하다: 또는 아마도 Fromxml / Toxml 함수를 갖는 기본 추상 클래스를 만들 수 있습니다. 그런 다음 초록 클래스에서 상속 된 함수를 사용하려는 모든 클래스를 사용하십시오.
다른 팁
모든 상속 클래스 및 적절한 다형성을 유지하기위한 정적 기본 클래스 방법을 갖는 것은 어렵습니다. 그러나 메소드의 정적 성을 제거하고 초기화 FROMXML 메소드가있어 본질적으로 XML에서 클래스를 채울 수 있습니다. 나는 일반적으로 공개 초기화 방법을 신경 쓰지 않지만, 이것은 다형성에 더 나은 경향이 있습니다.
여기 예입니다. 이와 같은 작은 물체에 대해서는 약간 많습니다 (그리고 실제로 XML 직렬화를 거의 사용하는 경우는 거의 없지만 XML 문서에로드하여 사막화 할당에 필요한 것을 꺼내려면) 복잡한 것은 훨씬 더 재사용 할 수 있습니다.
public class CustomObject {
public string AValue { get; set; }
public bool BValue { get; set; }
protected IXmlConfiguration Config = new CustomObjectConfig( );
public virtual string ToXml( ) {
return Config.ToXml( this );
}
public virtual void InitializeFromXml( string xml ) {
Config.FromXml( xml );
AValue = ((CustomObjectConfig)Config).A;
BValue = ((CustomObjectConfig)Config).B;
}
}
public interface IXmlConfiguration {
void FromXml( string xml );
string ToXml( object instance );
}
[XmlRoot( "CustomObject" )]
public class CustomObjectConfig : IXmlConfiguration {
[XmlElement( "AValue" )]
public string A { get; set; }
[XmlAttribute( "bvalue" )]
public bool B { get; set; }
public void FromXml( string xml ) {
byte[] bytes = Encoding.UTF8.GetBytes( xml );
using ( MemoryStream ms = new MemoryStream( bytes ) ) {
XmlSerializer xs = new XmlSerializer( typeof( CustomObjectConfig ) );
CustomObjectConfig cfg = (CustomObjectConfig)xs.Deserialize( ms );
A = cfg.A;
B = cfg.B;
}
}
public string ToXml( object instance ) {
string xml = null;
if ( instance is CustomObject ) {
CustomObject val = (CustomObject)instance;
A = val.AValue;
B = val.BValue;
using ( MemoryStream ms = new MemoryStream( ) ) {
XmlSerializer xs = new XmlSerializer( typeof( CustomObjectConfig ) );
xs.Serialize( ms, this );
ms.Seek( 0, 0 );
byte[] bytes = ms.ToArray( );
xml = Encoding.UTF8.GetString( bytes );
}
}
return xml;
}
}
XML 직렬화 가능한 객체를 만드는 대신이 접근법을 선호하는 이유는
- XML 직렬화는 일반적으로 클래스를 한쪽으로 구성해야하며 일반적으로 다른 방법으로 해당 클래스를 사용해야합니다.
- XML의 거대한 스택을 포함하는 것보다 약간 쉽습니다. 이는 파생 유형의 다형성 직렬화를 허용하는 모든 곳에서 속성 (다른 것으로 호출 될 수 있음)을 포함합니다.