C# 仅包含可序列化对象的字典

C# 仅包含可序列化对象的字典,c#,generics,serialization,dictionary,C#,Generics,Serialization,Dictionary,我正在寻找一种方法来确保在C#中只有可序列化对象存储到字典中 更具体地说,我希望做类似的事情: Dictionary<String, ISerializable> serialDict = new Dictionary<String, ISerializable>(); Dictionary serialDict=new Dictionary(); 问题是我不能存储像整数、布尔或字符串这样的基本类型 有没有办法确保我的字典只包含可以序列化的对象?我认为您不能在编译时这

我正在寻找一种方法来确保在C#中只有可序列化对象存储到字典中

更具体地说,我希望做类似的事情:

Dictionary<String, ISerializable> serialDict = new Dictionary<String, ISerializable>();
Dictionary serialDict=new Dictionary();
问题是我不能存储像整数、布尔或字符串这样的基本类型


有没有办法确保我的字典只包含可以序列化的对象?

我认为您不能在编译时这样做,但可以在运行时这样做。如果您从
字典
生成自己的类,那么在类的构造函数中,您可以检查附加到
TValue
类型的属性,并确保
SerializableAttribute
是其中之一,否则会引发异常


所有标准基元类型(
int
bool
等)都具有此属性。

如何包装词典

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 ...
}
class-SomeClass{
词典d;
//添加ISerializable
public void Add(字符串键,ISerializable值){
d[键]=值;
}
//添加基本类型
公共无效添加(字符串键,布尔值){
d[键]=值;
}
公共void Add(字符串键,int值){
d[键]=值;
}
//等等。。。
}
通过这种方式,您可以确保只能添加ISerializable对象和基本类型。

[Serializable]
[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));
        }
    }
}
公共类SerializableDictionary:字典 { 静态SerializableDictionary() { AssertSerializable(typeof(TKey)); AssertSerializable(typeof(TValue)); } 静态void AssertSerializable(类型t) { 如果(!t.IsSerializable) { 抛出新的NotSupportedException(string.Format( “{0}不可序列化”,t.Name)); } } }

一个要考虑的是,在可序列化的类中用与实现接口相反的标记。发件人:

任何可能被序列化的类都必须用 序列化属性。如果类需要控制其序列化 进程,它可以实现ISerializable接口

您需要做的是创建自己的类来实现接口,每次有人调用add时,使用反射来检查传入的元素是否具有可序列化属性(如果没有,则抛出异常)

代码看起来像

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();
        }
    }
    .....
}
类MyDictionary:IDictionary
{
私人词典d;
公共无效添加(TKey键,TValue值)
{
if(value.GetType().IsSerializable)
{
d、 添加(键、值);
}
其他的
{
抛出新ArgumentException();
}
}
.....
}

一个答案是创建一个SerializablePrimative包装类

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;
       }
   }
}
class SerializablePrimative:ISerializable{
private T val=default();
私有SerializablePrimative(T newVal){
val=newVal;
}
公共静态布尔值IsSupported(对象o){
如果(o==null){
返回false;
}否则{
返回IsSupported(o.GetType());
}
}
公共静态布尔值IsSupported(类型t){
如果(//您想支持*..)
{
返回true;
}
其他的
{ 
返回false;
}
}
公共静态SerializablePrimative GetSerializable(对象o){
如果(发布支持(o)){
return//intstatate通过反射**
}否则{
返回null;
}
}
}
其余部分留给读者作为练习,但基本上您需要创建一个适配器,以使这些特定类型“适合”您的词典

*另见:


**另请参见:

如果要在本词典中存储int、boolean和string,应选择何种类型作为TValue?@David Good point,+1。这是不受支持的。但是我读到这个问题时,似乎询问者想要存储这些类型中的一种,而不是它们的组合。根据MSDN文档,如果对象想要控制序列化过程,则只需要实现ISerializable接口。因此,没有任何可序列化对象实现此接口。感谢您的洞察力,这更有意义。我希望有一个编译时解决方案,但这将工作得很好。我也喜欢这个解决方案,这正是我的项目需要的东西。谢谢。这似乎有点过分了,因为给定的可序列化类(包括原语)已经用适当的属性标记了。