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.
Related
I need to declare a Dictionary having a Type as key and an instance as value.
I need to limit key Type to a certain class hierarchy.
For a Java Map, I can do something like:
Map<Class<? extends MySuperClass>, ? extends MySuperClass>
How can I achieve this in C#?
Do not expose Dictionary directly, this way you can control manually when to add
public void AddToDictionary(Type key, object value)
{
if(!key.IsAssignableFrom(typeof(SomeBaseClass))
throw new ArgumentException("Must be an inherited from SomeBaseClass type");
dictionary.Add(key, value);
}
I think Sinatr's approach of exposing a method for adding to the dictionary instead of the dictionary itself is a very good idea. The only downside is that you get no compile time safety; if some code added an object of the wrong type you wouldn't find out till runtime.
Using generics, however, we can tweak the method so that adding objects is foolproof:
public void AddToDictionary<T>(T value) where T: MySuperClass
{
dict.Add(typeof(T), value);
}
Now it is impossible to write a program that adds objects of the wrong type and still compiles.
You could use typeof to get the type of the class so something like:
Map<System.Type, object>
I am not sure how you would enforce the extends for this. That should probably happen as a test before adding to the map.
You could:
public class MyType<TBase>
{
private Type Value;
protected MyType()
{
}
public static implicit operator Type(MyType<TBase> type)
{
return type.Value;
}
public static implicit operator MyType<TBase>(Type type)
{
if (type == null)
{
throw new ArgumentNullException();
}
if (!typeof(TBase).IsAssignableFrom(type))
{
throw new ArgumentException();
}
return new MyType<TBase> { Value = type };
}
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
var type = obj as MyType<TBase>;
return type != null && Value.Equals(type.Value);
}
public override int GetHashCode()
{
return Value.GetHashCode();
}
public override string ToString()
{
return Value.ToString();
}
}
and then:
Dictionary<MyType<MySuperClass>, MySuperClass> dict = new Dictionary<MyType<MySuperClass>, MySuperClass>();
dict.Add(typeof(MyClass1), new MyClass1());
The MyType has implicit operators from/to Type, so it is quite simple to use. You simply cast a Type to a MyType (or a MyType to a Type) and it just works. Example of TryGetValue():
MySuperClass ms;
if (!dict.TryGetValue(typeof(MyClass1), out ms))
{
throw new Exception();
}
Note that the checks are done at runtime!
I've got a tree-structure-class called ConfigNode (similar to SerializationInfo), which can store configuration values in a list and controls child nodes. When I add IEnumerable<ConfigNode> as interface to derive from, protobuf-net fails during serialization and causes a StackOverFlowException, even with the IgnoreListHandling flag set to true.
[Serializable, DataContract, ProtoContract(IgnoreListHandling = true)]
public class ConfigNode : Entity, ICloneable, INotifyPropertyChanged
{
[DataMember, ProtoMember(1)]
private Dictionary<String, PrimitiveSurrogate> values = new Dictionary<String, PrimitiveSurrogate>();
private Dictionary<String, ConfigNode> _Childs = new Dictionary<String, ConfigNode>();
[DataMember, ProtoMember(2)]
public Dictionary<String, ConfigNode> Childs
{
get
{
return _Childs;
}
private set
{
_Childs = value;
}
}
[DataMember, ProtoMember(3)]
public ConfigNode Parent { get; set; }
}
is working fine. PrimitiveSurrogate is a struct storing nullables of all commonly used "almost-primitives" like String, Guid, DataTime, float / double, bool, char, etc. The config values themselves will be added in a "Store"-method which is of no importance. It takes an object as parameter and tries to cast the type to one of the storable data types and stores it the strongly typed PrimitiveSurrogate. The entity base-class just provides a Name-property, nothing else.
But as soon as I add IEnumerable<ConfigNode> to the list of interfaces and add the appropriate methods (see below), any serialization attempts throw a StackOverflowException.
public void Add(ConfigNode child)
{
if (child == null)
throw new ArgumentNullException("child");
if (child.Name == null)
throw new ArgumentException("The child's name was null. The child cannot be added.");
child.Parent = this;
lock (this.Childs)
{
this.Childs[child.Name] = child;
}
}
public IEnumerator<ConfigNode> GetEnumerator()
{
lock (this.Childs)
{
return this.Childs.Values.Clone().GetEnumerator();
}
}
IEnumerator IEnumerable.GetEnumerator()
{
lock (this.Childs)
{
return this.Childs.Values.Clone().GetEnumerator();
}
}
"Clone" is an extension method and looks like this:
public static IEnumerable<T> Clone<T>(this IEnumerable<T> collection)
{
return collection.ToList();
}
It seems like protobuf-net ignores the IgnoreListHandling-flag, can anyone help?
Nevermind, I found the mistake. After some changes I introduced a lock in the Childs-Property and in Childs.get() I was locking the property itself and not the backing field. This caused a StackOverflow due to the Monitor-Class trying to access the property and causing the get-Accessor to be accessed again.
It now (de)serializes smoothly.
Fixed version:
[DataMember, ProtoMember(2)]
public Dictionary<String, ConfigNode> Childs
{
get
{
lock (_Childs)
{
return _Childs;
}
}
private set
{
lock (_Childs)
{
_Childs = value;
}
}
}
When is it acceptable for an indexer to automatically add items to a collection/dictionary? Is this reasonable, or contrary to best practices?
public class I { /* snip */ }
public class D : Dictionary<string, I>
{
public I this[string name]
{
get
{
I item;
if (!this.TryGetValue(name, out item))
{
item = new I();
this.Add(name, item);
}
return item;
}
}
}
Sample of how this may be used in a collection:
public class I
{
public I(string name) {/* snip */}
public string Name { get; private set; }
/* snip */
}
public class C : Collection<I>
{
private Dictionary<string, I> nameIndex = new Dictionary<string, I>();
public I this[string name]
{
get
{
I item;
if (!nameIndex.TryGetValue(name, out item))
{
item = new I(name);
this.Add(item); // Will also add the item to nameIndex
}
return item;
}
}
//// Snip: code that manages nameIndex
// protected override void ClearItems()
// protected override void InsertItem(int index, I item)
// protected override void RemoveItem(int index)
// protected override void SetItem(int index, I item)
}
There's two problems that you should consider - both of which suggest this is a bad idea.
First, inheriting from the .NET BCL collection types is not generally a good idea. The main reason for this is that most methods on those types (like Add and Remove) are not virtual - and if you provide your own implementations in a derived class, they will not get called if you pass your collection around as the base type. In your case, by hiding the Dictionary<TK,TV> indexer property, you are creating a situation where a call using a base-class reference will do something different than a call using a derived-class reference ... a violation of the Liskov Substitution Principle:
var derived = new D();
var firstItem = derived["puppy"]; // adds the puppy entry
var base = (Dictionary<string,I>)derived;
var secondItem = base["kitten"]; // kitten WAS NOT added .. BAD!
Second, and more importantly, creating an indexer that inserts an item when you attempt to find one is entirely unexpected. Indexers have clearly defined get and set operations - implementing the get operation to modify the collection is very bad.
For the case you describe, you're much better off creating an extension method that can operate on any dictionary. Such an operation is both less surprising in what it does, and also doesn't require creating a derived collection type:
public static class DictionaryExtensions
{
public static TValue FindOrAdd<TKey,TValue>(
this IDictionary<TKey,TValue> dictionary, TKey key, TValue value )
where TValue : new()
{
TValue value;
if (!this.TryGetValue(key, out value))
{
value = new TValue();
this.Add(key, value);
}
return value;
}
}
With no other information about what you're doing, that looks like surprising behavior to me. I hope that you make it very clear from the context (i.e. name it an AutoInitializingDictionary or something) what's to be expected.
I would personally prefer to make this a method rather than an indexer; something like D.FindOrCreate. (I have the feeling there's an idiomatic name for a method that does this which I've temporarily forgotten.)
I would say this violates two principles. 1) principle of least surprise. And 2) that getters shouldn't change anything.
I wouldn't expect to add a the pair {"foo", null} if foo doesn't exist in the colleciton.
x = collection["Foo"]
I think it is perfectly fine as long as this behaviour is made perfectly clear. I have 2 decorator classes:
public class DefaultValueDictionary<K, V> : IDictionary<K, V>
{
public DefaultValueDictionary(IDictionary<K, V> baseDictionary, Func<K, V> defaultValueFunc)
{
...
}
}
and
public class ParameterlessCtorDefaultValueDictionary<K, V>
: DefaultValueDictionary<K, V> where V : new()
{
public ParameterlessCtorDefaultValueDictionary(IDictionary<K, V> baseDictionary)
: base(baseDictionary, k => new V())
{
...
}
}
The second class is perfect for counters and patterns like IDictionary<K,List<V>>;
I can do
var dict = new ParameterlessCtorDefaultValueDictionary<string, int>();
...
dict[key]++;
instead of the laborious:
int count;
if(!dict.TryGetValue(key, out count))
dict[count] = 1;
else dict[count] = count + 1;
The primary reason I would be concerned is that it wouldn't be thread-safe. Multiple readers all attempting to possibly write to the Dictionary at once would require careful lock management that you wouldn't likely think of (or get right) at first.
When is it acceptable for an indexer
to automatically add items to a
collection/dictionary?
Never
Is this reasonable, or contrary to
best practices?
Contrary to best practices
That said, if the class is named appropriately, it'd be acceptable. I'd personally use GetOrAdd instead.
I have a dictionary as follows:
IDictionary<string, string> dict;
How to create an enumerator that implements IDictionaryEnumerator (preferably using linq)?
Must be missing something here, what about:
IDictionary obsoleteDict = dict as IDictionary;
if (obsoleteDict == null)
{
//Do something here...
}
else
{
return obsoleteDict.GetEnumerator();
}
(edit: yep, you have to cast it to the old non-generic interface)
edit2: see Pavel's comment below. A type implementing IDictionary<K,V> may or may not implement IDictionary (Dictionary<K,V> does while some implementations like WCF's MessageProperties do not) so the cast may not work.
IDictionaryEnumerator is really the pre-generics version; you should just be able to use IEnumerator<KeyValuePair<string,string>>...
You could encapsulate, of course; this will then work even for custom implementations:
using System;
using System.Collections;
using System.Collections.Generic;
static class Program
{
class MyEnumerator<TKey,TValue> : IDictionaryEnumerator, IDisposable
{
readonly IEnumerator<KeyValuePair<TKey, TValue>> impl;
public void Dispose() { impl.Dispose(); }
public MyEnumerator(IDictionary<TKey, TValue> value)
{
this.impl = value.GetEnumerator();
}
public void Reset() { impl.Reset(); }
public bool MoveNext() { return impl.MoveNext(); }
public DictionaryEntry Entry { get { var pair = impl.Current;
return new DictionaryEntry(pair.Key, pair.Value);} }
public object Key { get { return impl.Current.Key; } }
public object Value { get { return impl.Current.Value; } }
public object Current {get {return Entry;}}
}
static IDictionaryEnumerator GetBasicEnumerator<TKey,TValue>(
this IDictionary<TKey, TValue> data)
{
return new MyEnumerator<TKey, TValue>(data);
}
static void Main()
{
IDictionary<int, string> data = new Dictionary<int, string>()
{
{1,"abc"}, {2,"def"}
};
IDictionaryEnumerator basic;
using ((basic = data.GetBasicEnumerator()) as IDisposable)
{
while (basic.MoveNext())
{
Console.WriteLine(basic.Key + "=" + basic.Value);
}
}
}
}
I believe that IDictionaryEnumerator is only implemented by non-generic dictionary types. The generic dictionary classes expose IEnumerator.
Since generic dictionaries return strongly typed KeyValuePair items, the features of IDictionaryEnumerator seem redundant. You should try to adapt your code if possible to just use IEnumerator<KeyValuePair<K,V>>.
In most cases, this will work. Then ones where it doesn't will throw an exception.
return (IDictionaryEnumerator)dict.GetEnumerator();
At least the following BCL types return enumerators that implement IDictionaryEnumerator (these are the ones I checked):
Hashtable (public API enforced)
Dictionary<T,K> (public API enforced)
SortedList<T,K> (not guaranteed by the public API, but the implementation does implement it)
I have a class like this:
public class SomeClass
{
private const string sessionKey = "__Privileges";
public Dictionary<int, Privilege> Privileges
{
get
{
if (Session[sessionKey] == null)
{
Session[sessionKey] = new Dictionary<int, Privilege>();
}
return (Dictionary<int, Privilege>)Session[sessionKey];
}
}
}
Now, if Ido this...
var someClass = new SomeClass();
var p = someClass.Privileges[13];
... and there is no key 13, I will get an error like this:
The given key was not present in the dictionary.
I would like to have a property that can be accessed in the same way as above, but will return a default object in case of the absence of the key.
I tried creating an indexer property like this...
public Privilege Privileges[int key]
{
get
{
try { return _privileges[key]; }
catch { return new Privilege(); }
}
}
... but it looks like that's not a C# 2008 language feature.
How can I access the property in the same way, but get the default object if the key isn't present?
C# does not supported named indexers, as you have discovered.
Have you considered using a regular method instead of an indexer property? Not every programming problem requires the use fancy syntax to solve. Yes, you could create your own IDictionary implementation with an aggregated dictionary and change the property access behavior - but is that really necessary for something that just fetches a value or returns a default?
I would add a method like this to your class:
protected Privilege GetPrivilege(int key)
{
try { return _privileges[key]; }
catch { return new Privilege(); }
}
or better yet, avoid exception handling as a flow control mechanism:
protected Privilege GetPrivilge( int key )
{
Privilege priv;
if( _privileges.TryGetValue( key, out priv ) )
return priv;
else
return new Privilege();
}
You'll have to define your own IDictionary-based class with an indexer that has the desired behavior, and return an instance of that, rather than the stock Dictionary class, in your property getter.
Indexers in C# can only be used with the this keyword.
I suspect you want something like this:
public Privilege this[int key]
{
get
{
try { return _privileges[key]; }
catch { return default(Privelege); }
}
}
which you can define either directly in SomeClass so that you can access a privelege item like:
SomeClass foo;
var bar = foo[100];
or define this indexer in a custom class that implements from IDictionary<TKey, TValue> (and contains a Dictionary<TKey, TValue internally for actually storing the data). You could then use it like:
SomeClass foo;
var bar = foo.Priveleges[100];
Which is the syntax you seem to propose, and which may be most appropiate, though it takes a bit more effort.
You should use this syntax to retrieve the value:
public Privilege this[int key]
{
get
{
var value = (Privilege)null;
if(!_privileges.TryGetValue(key, out value))
value = new Privilege();
return value;
}
}
I have a need for this kind of use of IDictionary a lot, so I made some extension methods:
public static TValue Get<TKey, TValue>(this IDictionary<TKey, TValue> d, TKey key)
{
TValue v = default(TValue);
d.TryGetValue(key, out v);
return v;
}
public static TValue Get<TKey, TValue>(this IDictionary<TKey, TValue> d, TKey key, Func<TValue> value)
{
TValue v = d.Get(key);
if (v == null)
{
v = value();
d.Add(key, v);
}
return v;
}
Now you could write:
public Privilege this[int key]
{
get
{
return _privileges.Get(key, () => new Privilege());
}
}