Dictionary containing with only Serializable objects
I am looking for a way to ensure that only serializable objects are stored into a Dictionary in C#.
To be more specific I'm looking to do something similar开发者_如何学编程 to this:
Dictionary<String, ISerializable> serialDict = new Dictionary<String, ISerializable>();
The problem with this is that I cannot store primitive types like integers, booleans, or strings.
Is there a way to ensure that my Dictionary contains only objects which can be serialized?
I don't think you can do this at compile-time, but you can do it at runtime. If you build your own class deriving from Dictionary<TKey, TValue>
, then in the constructor of your class, you can check the attributes attached to the TValue
type, and make sure SerializableAttribute
is one of them, else throw an exception.
All of the standard primitive types (int
, bool
, etc.) have this attribute.
One thing to consider is that in classes that are serializable are tagged with the SerializableAttribute as opposed to implementing an interface. From MSDN:
Any class that might be serialized must be marked with the SerializableAttribute. If a class needs to control its serialization process, it can implement the ISerializable interface.
What you would need to do is make your own class that implements the IDictioanry interface and every time someone calls add, use reflection to check if the element passed in has a serializable attribute (and throw an exception if it doesn't).
Code would look something like
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();
}
}
.....
}
[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));
}
}
}
One answer would be to create a SerializablePrimative wrapper class.
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;
}
}
}
The rest is left as an exercise to the reader, but basically your creating an adapter to make these certain types "fit" your dictionary.
*See Also: Types Supported by the Data Contract Serializer
**See Also: C#: Using Reflection to Instantiate a Generic Class in .Net
What about wrapping your dictionary?
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 ...
}
In this way you are sure that only ISerializable objects and primitive types can be added.
精彩评论