2009-10-08 3 views
1

ActiveRecord 객체를 우아하게 직렬화하는 방법에 대한 정보를 찾는 데 어려움을 겪고 있습니다.C# Castle ActiveRecord : 우아하게 (XML) ActiveRecord 객체를 직렬화하는 방법?

우리는 다른 프로그램이이를 해석 할 수있는 방식으로 객체를 출력해야하므로 XML을 형식으로 사용하고자합니다.

XML 직렬화는 일반적으로 매우 쉽고 구현하기 쉽지만 ActiveRecord 데이터베이스에서 반환 된 객체를 직렬화하려고하면 문제가 발생합니다. 데이터베이스는 객체의 프록시 클래스를 반환합니다. 객체의 유형은 [XmlInclude] 속성을 통해 명시 적으로 예상 할 수 없습니다. 예를 들어

:

public class Foo : ActiveRecordLinqBase<Foo> 
{ 
    public virtual string Bar{get;set;} 

    public virtual int FooId{get;set;} 

    public Foo(string bar) 
    { 
     Bar = bar; 
    } 

    public static void FooSerializeExample() 
    { 
     Foo tehFoozor = new Foo("omgFoo!"); 
     tehFoozor.SaveAndFlush(); 
     int id = tehFoozor.FooId; 

     //... 
     //Assume new ActiveRecord session. 

     XmlSerializer serializer = new XmlSerializer(typeof(Foo)); 

     Foo tehFoozorToSerialize = Foo.Find(id); 

     using(Stream stream = File.OpenWrite("tehFoozor.xml")) 
     { 
     serializer.Serialize(stream, tehFoozorToSerialize); //Will fail 
     } 
    } 
} 

여기 직렬화 할 때, 우리는 메시지를 얻을 것이다 :.
는 "FooProxy2e2de24df9be42909d13a67fdb00b981 예상하지 않은 유형은 정적으로 알 수없는 유형을 지정합니다 XmlInclude 또는 SoapInclude 속성을 사용합니다. "

프록시 유형은 완전히 예측할 수 없습니다 (적어도 내 지식에 따라).

우리 팀은 일시적인 해결책으로 각 AR 개체의 속성을 인터페이스에 스텁 아웃했습니다. 그런 다음 각 객체에 대해 Xml-Serializable 비 AR 버전 인 "컨테이너"객체를 구현했습니다. 우리가 현재 직렬화 된 18 개의 다른 AR 객체를 가지고 있다는 사실을 고려하면, 우리의 솔루션에 36 개의 추가 파일이 있습니다! 무언가 (모든 것)는 이것이 나쁜 해결책이라고 말하지만, 나는 더 나은 방법을 찾을 수 없었습니다.

또한 비누 포맷터를 사용해 보았지만 ActiveRecrodLinqBase <>은 "직렬화 가능으로 표시되어 있지 않습니다"이후로 역시 막 다른 골목이었습니다.

+0

더 많은 검색을 한 후에, 나는 이것이 "지연로드"를 사용하고 있기 때문에 발생하는 이유를 발견했습니다. 로드하는 객체에는 Microsoft MVC를 통해로드되고 표시 될 수있는 수천 개의 파트가 포함되는 심층적 인 계층 구조가 있기 때문에 절충안이 아닙니다. 고위 개발자 중 한 명은 가능한 해결 방법으로 반영되도록 대기하고 있습니다.다른 누구도이 일을 겪어 본 적이 있습니까? – Anj

답변

3

필요로하는 것을 모두 가져 와서 AutoMapper을 사용하여 DTO에 매핑하고 해당 DTO를 직렬화하십시오.

당신이 얻는 프록시 오류는 일반 List<T> 또는 배열을 대신 사용해야 할 때 DTO가 실제로 NHibernate의 프록시 된 컬렉션을 사용하고 있음을 나타냅니다. ToList() 또는 그 유사 물체를 사용하십시오.

또한 인터페이스를 사용하여 DTO를 매핑 할 필요가 없습니다.

+0

동의합니다 .. 절대 실제 물건을 철로에 보내지 마십시오. Ayende는 이것에 대해 한 번 쓴 적이 있는데 그와 동의합니다 : http://ayende.com/Blog/archive/2009/05/14/the-stripper-pattern.aspx – Tigraine

+0

나는 실수 할 수는 있지만 이것이 우리가 생각하는 것입니다. 이미이 작업을 수행하고 있습니다 : 개체를 개체의 기본 복제본으로 매핑 한 다음 (이를 AutoMapper를 사용하지 않아 매핑 프로세스를 단순화하지 못했기 때문에) 객체를 직렬화합니다. 이전에 언급했듯이이 방법은 36 개의 파일을 솔루션에 추가하며 단위 테스트 파일은 포함하지 않습니다. @Tigraine : 와이어를 통해 실제 오브젝트를 보내지는 않지만 와이어를 통해 보낼 데이터를 얻을 때 각 오브젝트의 일부를로드해야합니다. 이것이 우리가 게으른 로딩을 필요로하는 이유입니다. – Anj

+0

맞습니다. 이미 DTO를 사용하고 있지만 DTO 매핑이 적절하지 않은 것으로 보입니다. 내 업데이트 답변을 참조하십시오. –

0

DataContractSerializer를 사용해보십시오.

해당 [XmlInclude]는 [KnownType]이며 유형이 처음 반영 될 때 유형을 동적으로 제공 할 수있는 버전을 포함합니다. http://msdn.microsoft.com/en-us/library/ms730167.aspx

또한, .NET4.0에는 특히이 같은 시나리오를 만드는 DataContractSerializer의 "Type Mapper"기능이 포함될 것이라고 생각합니다 (100 % 확신 할 수는 없지만).

DCS를 끝내고 질문이 생기면이 대답에 의견으로 게시하면 답변을 드리겠습니다.

+0

이 솔루션이 실행 가능한지 테스트하고 여기에서 결과를 업데이트하십시오. 감사! – Anj

관련 문제