2011-08-12 2 views
6

직렬화 가능 개체 만 C#의 사전에 저장되도록하는 방법을 찾고 있습니다. Serializable 개체 만 포함하는 사전

내가이 비슷한 뭔가를 찾고 있어요 더 구체적으로 :

Dictionary<String, ISerializable> serialDict = new Dictionary<String, ISerializable>(); 

이 가진 문제는 내가 정수, 부울 또는 문자열과 같은 기본 유형을 저장할 수 없다는 것입니다.

내 사전에 일련 번호를 지정할 수있는 객체 만 포함되도록하는 방법이 있습니까?

답변

4

나는 이것을 컴파일 타임에 할 수 있다고 생각하지 않지만, 당신은 런타임에 그것을 할 수있다. Dictionary<TKey, TValue>에서 파생 된 클래스를 작성한 경우 클래스의 생성자에서 TValue 유형에 첨부 된 속성을 점검하고 SerializableAttribute이 그 중 하나인지 확인하고 예외를 던집니다.

모든 표준 기본 유형 (int, bool 등)에는이 속성이 있습니다.

+0

C#: Using Reflection to Instantiate a Generic Class in .Net이 통찰력을 주셔서 감사합니다,이 더 의미가 있습니다. 나는 컴파일 시간 솔루션을 원했지만 이것은 정상적으로 작동 할 것이다. – LamdaComplex

0

사전은 어떻게 포장합니까?

class SomeClass { 

    Dictionary<string,object> d; 
    // add ISerializable 
    public void Add(string key, ISerializable value) { 
     d[key] = value; 
    } 
    // add primitive types 
    public void Add(string key, bool value) { 
     d[key] = value; 
    } 
    public void Add(string key, int value) { 
     d[key] = value; 
    } 
    // etc ... 
} 

이렇게하면 ISerializable 개체와 기본 유형 만 추가 할 수 있습니다. 고려해야 할

+1

MSDN 설명서에 따르면 객체는 직렬화 프로세스를 제어하려는 경우 ISerializable 인터페이스 만 구현하면됩니다. 따라서 모든 직렬화 가능 객체가이 인터페이스를 구현하지는 않습니다. – R0MANARMY

1
[Serializable] 
public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue> 
{ 
    static SerializableDictionary() 
    { 
     AssertSerializable(typeof(TKey)); 
     AssertSerializable(typeof(TValue)); 
    } 

    static void AssertSerializable(Type t) 
    { 
     if (!t.IsSerializable) 
     { 
      throw new NotSupportedException(string.Format(
       "{0} is not serializable", t.Name)); 
     } 
    } 
} 
+1

int, boolean 및 문자열을이 사전에 저장하려면 TValue로 어떤 유형을 선택해야합니까? –

+0

@ David 좋은 지적, +1. 그건 지원되지 않습니다. 그러나 나는 질문자가 묻는 사람이이 유형들 중 하나를 저장하고 싶은 것이지, 그것들을 조합하지는 않는 것처럼 읽었다. –

2

한 가지 인터페이스를 구현 반대로 직렬화 된 클래스에 SerializableAttribute 태그한다는 것이다. MSDN에서 :

SerializableAttribute로 표시되어야합니다 직렬화 할 수있는 클래스입니다. 클래스가 직렬화 프로세스를 제어해야하는 경우 ISerializable 인터페이스를 구현할 수 있습니다.

당신은 아무튼 경우 전달 된 요소가 직렬화 속성이 있는지 확인하기 위해 IDictioanry 인터페이스와 때마다 누군가가 추가 호출, 사용 반사를 구현하는 자신의 클래스를 만들어 (그리고 예외를 발생한다 할 필요가 무엇 '티).

코드는 SerializablePrimative 래퍼 클래스를 생성하는 것입니다

class MyDictionary<TKey, TValue> : IDictionary<TKey, TValue> 
{ 
    private Dictionary<TKey, TValue> d; 

    public void Add(TKey key, TValue value) 
    { 
     if(value.GetType().IsSerializable) 
     { 
      d.Add(key, value); 
     } 
     else 
     { 
      throw new ArgumentException(); 
     } 
    } 
    ..... 
} 
+0

나는이 솔루션을 좋아한다. 프로젝트에 꼭 필요한 것이다. 고맙습니다. – LamdaComplex

1

한 대답과 같을 것입니다.

class SerializablePrimative<T> : ISerializable { 
    private T val = default(); 

    private SerializablePrimative(T newVal){ 
     val = newVal; 
    } 

    public static boolean IsSupported(Object o){ 
     if (o == null){ 
      return false; 
     }else{ 
      return IsSupported(o.GetType()); 
     } 
    } 

    public static boolean IsSupported(Type t){ 
     if (// you want to support* ...) 
     { 
      return true; 
     } 
     else 
     { 
     return false; 
     } 
    } 

    public static SerializablePrimative GetSerializable(Object o){ 
     if (IsSupported(o)){ 
      return //Intstatiate via Reflection ** 
     }else { 
      return null; 
     } 
    } 
} 

나머지는 독자에게 연습 문제로 남겨 두지 만 기본적으로 이러한 특정 유형을 사전에 적합하게 만드는 어댑터입니다.

* 참조 : Types Supported by the Data Contract Serializer

이 ** 참조 :

+0

이것은 직렬화 가능한 클래스 (프리미티브 포함)에 이미 적절한 속성으로 태그가 지정되어있어 과도한 것처럼 보입니다. – R0MANARMY

관련 문제