2013-11-27 4 views
8

DataContractSerializer을 사용하는 제네릭 형식을 포함하는 XML 파일에 클래스를 저장 /로드하려고합니다. 저장 작업이 있지만 deserializer의 knownTypes 목록이 없기 때문에로드 할 수 없다는 것을 알았습니다.형식을 참조하지 않고 제네릭을 deserialize 할 수 있습니까?

저장된 클래스를 직접 참조하지 않고도이 클래스를 직렬화 해제 할 수있는이 클래스를 serialize/deserialize 할 수 있습니까?

[DataContract] 
public class SessionVariables 
{ 
    [DataMember] 
    private Dictionary<Type, ISessionVariables> _sessionVariables = new Dictionary<Type, ISessionVariables>(); 
    private object _syncLock = new object(); 

    public T Get<T>() 
     where T : ISessionVariables, new() 
    { 
     lock (_syncLock) 
     { 
      ISessionVariables vars = null; 

      if (_sessionVariables.TryGetValue(typeof(T), out vars)) 
       return (T)vars; 

      vars = new T(); 
      _sessionVariables.Add(typeof(T), vars); 

      return (T)vars; 
     } 
    } 

    public IList<Type> GetKnownTypes() 
    { 
     IList<Type> knownTypes = new List<Type>(); 

     knownTypes.Add(this.GetType().GetType()); // adds System.RuntimeType 

     foreach (Type t in _sessionVariables.Keys) 
     { 
      if (!knownTypes.Contains(t)) 
       knownTypes.Add(t); 
     } 

     return knownTypes; 
    } 
} 

응용 프로그램의 다른 모듈

이 같은 세션 변수의 자신의 세트를 만들 수 ISessionVariables 인터페이스를 확장 :

다음

내가 /로드를 저장하려고 내 SessionVariables 클래스

그리고 SessionVariables 클래스의 단독 인스턴스

[DataContract] 
public class ModuleASessionVariables : ISessionVariables 
{ 
    [DataMember] 
    public string ModuleA_Property1{ get; set; } 
    [DataMember] 
    public string ModuleA_Property2 { get; set; } 
} 


[DataContract] 
public class ModuleBSessionVariables : ISessionVariables 
{ 
    [DataMember] 
    public string ModuleB_Property1{ get; set; } 
    [DataMember] 
    public string ModuleB_Property2 { get; set; } 
} 
은 다음과 같이 세션 변수에 액세스하는 데 사용됩니다

using (FileStream writer = new FileStream(@"C:\test.txt", FileMode.Create)) 
{ 
    DataContractSerializer dcs = new DataContractSerializer(typeof(SessionVariables), singletonSessionVariables.GetKnownTypes()); 
    dcs.WriteObject(writer, singletonSessionVariables); 
    writer.Close(); 
} 

그러나이 방법은 내가이 유형 알려진 모르기 때문에 클래스를 직렬화하기 위해 작동하지 않습니다
singletonSessionVariables.Get<ModuleASessionVariables>().ModuleA_Property1 
singletonSessionVariables.Get<ModuleBSessionVariables>().ModuleB_Property2 

0 I는 다음과 같이 작업을 저장할 수 있어요.

사용 된 유형에 대한 직접적인 라이브러리 참조가 없을 때 제네릭 형식을 직렬화 및 비 직렬화 할 수 있습니까? 그렇다면 어떻게?

+1

:/결과에 형식 정보가 포함 된 NetDataContractSerializer를 사용합니다. – Will

+0

가능하지 않다고 생각합니다. 형식 자체가 알려지지 않은 경우 어떻게 형식의 인스턴스를 만들까요? – Tigran

+0

@Will 감사합니다. 이전에는 존재하지 않았다. 이 질문에 대한 답변을 작성해야합니다 :) – Rachel

답변

3

문제는 여기에 당신은 단지 데이터를 직렬화하고 싶은되지 않습니다,하지만 당신은 또한 메타 데이터을, 즉 데이터에 대해 데이터를 직렬화 (극적인 다람쥐를 큐)하고 싶다.

이 메타 데이터는이 경우 원래 데이터를 보유한 모델의 유형입니다. 일반적으로 이것은 문제가 아니지만 디자인에서 다형성을 활용하는 경우 단일 컬렉션에 두 개 이상의 다른 유형이 포함될 수 있습니다. 각 유형은 원래 유형으로 직렬화 될 필요가 있습니다.

일반적으로이 형식 메타 데이터를 serialize 된 결과에 저장하면됩니다. 다른 직렬화 방법은 여러 가지 방법으로이 작업을 수행합니다. Xaml serialization은 .net 네임 스페이스와 관련된 xml 네임 스페이스를 사용하고 원래 형식 이름 뒤에 요소의 이름을 지정합니다. Json.net은 json 객체에 저장된 특정 명명 된 값을 통해이를 수행합니다.

기본 DataContractSerializer는 형식을 인식하지 못합니다. 따라서 .NET 형식 시스템을 이해하고 버전 메타 데이터를 결과 XML에 serialize/deserialize 할 수있는 버전으로 대체해야합니다. 다행히 프레임 워크에 이미 존재하는 것은 NetDataContractSerializer입니다.

그래서 링크 전용 답변을 덧붙입니다. 귀족.

+0

필요한 외부 모듈 라이브러리에 대한 참조없이이 방법은 훌륭했습니다. 내가해야만하는 유일한 변화는'_syncLock' 객체를'[DataMember]'속성으로 표시하거나''null ''로 역 직렬화하는 것입니다. 지금 그 길을 찾고 있습니다. 감사합니다 :) – Rachel

0

사용자 지정 DataContractResolver를 사용하여이 작업을 수행 할 수 있습니다. 이를 통해 직렬화 된 파이프 라인에 연결하고 직렬화 된 그래프에있는 유형/네임 스페이스를 기반으로 역 직렬화 할 유형을 제공 할 수 있습니다.http://idesign.net/Downloads/GetDownload/1848가 (당신은 아마 제네릭을 처리 할 수있는 몇 가지 수정을해야합니다 : http://blogs.msdn.com/b/carlosfigueira/archive/2011/09/21/wcf-extensibility-data-contract-resolver.aspx

IDesign의가 자신의 사이트에 유형의 동적 발견에 사용할 수있는 해결의 구현이 있습니다

는 여기에 좋은 기사입니다)

+1

당신을위한 참고 :이 솔루션은 필요합니다. 넷 4-- 난 그냥 .net3-5 태그를 귀하의 질문에 나타났습니다. – JMarsch

관련 문제