How to: dynamically create a Dictionary<k,v>

G

Guest

Imagine a class MasterStore carries a private hashtable. The hashtable will
carry 1 or more Dictionary<k,v>. MasterStore has a public method called
AddStore that adds new typed dictionaries to the master dict.

The dictionaries stored in the hashtable can all be of different types (i.e.
Dictionary<string,Customer> or Dictionary<string,Order>). What's important is
that all of the types in a specific Dictionary are all the same.

Can anyone point out a way to dynamically create a new Dictionary? The
method in AddStore will not compile.

I would not be surprised if this required runtime creation of code. That
would be acceptable for this issue.

public class MasterStore
{
private HashTable _storeMaster = new HashTable();

public void AddStore(System.Type t, string name)
{
_masterStore.Add(name, new DataStore<t>(name));

}
}

the goal is to make calls like

mStore.AddStore( typeof(Customer), 'customers')
mStore.AddStore( typeof(Order), 'orders' )

and have the appropriate Dictionary created for each line.
 
G

Guest

sorry code should be as shown below.

DataStore is a wrapper class i created. I corrected the code below.

public class MasterStore
{
private HashTable _storeMaster = new HashTable();

public void AddStore(System.Type t, string name)
{
_masterStore.Add(name, new Dictionary<string,t>());

}
}

--
====================

eAndy

====================
 
J

James Irvine

eAndy said:
Imagine a class MasterStore carries a private hashtable. The hashtable will
carry 1 or more Dictionary<k,v>. MasterStore has a public method called
AddStore that adds new typed dictionaries to the master dict.

The dictionaries stored in the hashtable can all be of different types (i.e.
Dictionary<string,Customer> or Dictionary<string,Order>). What's important is
that all of the types in a specific Dictionary are all the same.

Can anyone point out a way to dynamically create a new Dictionary? The
method in AddStore will not compile.

I would not be surprised if this required runtime creation of code. That
would be acceptable for this issue.

public class MasterStore
{
private HashTable _storeMaster = new HashTable();

public void AddStore(System.Type t, string name)
{
_masterStore.Add(name, new DataStore<t>(name));

}
}

the goal is to make calls like

mStore.AddStore( typeof(Customer), 'customers')
mStore.AddStore( typeof(Order), 'orders' )

and have the appropriate Dictionary created for each line.



using System;
using System.Data;
using System.Collections.Generic;

public class profanityCheck
{
public string profanityCheckX(string searchText)
{
string textEntered = searchText.ToLower();
string offender = "ok";

Dictionary<byte, string> dicTable = new Dictionary<byte, string>();
dicTable.Add(1, "aaaa");
dicTable.Add(2, "bbbb");
dicTable.Add(3, "cccc");


foreach (KeyValuePair<byte, string> objKVP in dicTable)
{
string aBadWordEntry = objKVP.Value.ToString().ToLower();
int at = textEntered.IndexOf(aBadWordEntry);
if (at != -1)
{
offender = aBadWordEntry;
break;
}
}
return offender;
}
}
 
G

Guest

looks like a nice sample on how to use dictionary but doesn't answer my
question.

The twist is that the type of the dictionary is not known until runtime.

In the example you show below the Dictionary<byte,string> is known at
compile time.

In my example, the types used for the key and value are not know until the
AddStore is called.

Due to the way that generics are implemeted scenarios where the types are
not known until runtime is more complex.

Anyone else got a sample that addresses this?
--
====================

eAndy

====================
 
J

Jon Skeet [C# MVP]

eAndy said:
looks like a nice sample on how to use dictionary but doesn't answer my
question.

The twist is that the type of the dictionary is not known until runtime.

In the example you show below the Dictionary<byte,string> is known at
compile time.

In my example, the types used for the key and value are not know until the
AddStore is called.

Due to the way that generics are implemeted scenarios where the types are
not known until runtime is more complex.

Anyone else got a sample that addresses this?

Well, you could use reflection to get the appropriate generic type, and
construct an instance from that. However, is it actually going to
achieve anything for you? What's the benefit of using the generic
dictionary in this case?

If the *caller* always knows the type at compile time, by the way, you
could make it a generic method:

public void AddStore<T>(string name)
{
_masterStore.Add(name, new DataStore<T>(name));
}

That's also clearer (IMO) in the calling code:

AddStore<Order>(name);

vs

AddStore(typeof(Order), name);

It's only applicable when the callers know the type involved however.
 
S

sternr

Hey,
I think this is what you meant:


public object CreateGenericDictionary(Type key, Type val)
{
Type origType = typeof(Dictionary<,>);
Type genType = origType.MakeGenericType(key, val);
return genType.Assembly.CreateInstance(genType.FullName);
}

Hope this helps,

--sternr
 
C

Chris Shepherd

public class MasterStore
{
private HashTable _storeMaster = new HashTable();

public void AddStore(System.Type t, string name)
{
_masterStore.Add(name, new DataStore<t>(name));

}
}


Silly question, but are these variables named correctly? If the only
code in question is the code you have listed, of course it won't work --
you're using _storeMaster and _masterStore.

Assuming however that you just fudged the code a bit when posting it
here and that it's a typo, James/Jon have already got it covered.

Chris.
 
B

Ben Voigt [C++ MVP]

sternr said:
Hey,
I think this is what you meant:


public object CreateGenericDictionary(Type key, Type val)
{
Type origType = typeof(Dictionary<,>);
Type genType = origType.MakeGenericType(key, val);
return genType.Assembly.CreateInstance(genType.FullName);

Oh no... once you have the Type, don't convert it to a name (string) and
back again.

Use Activator.CreateInstance instead, or Type.GetConstructor and call its
Invoke method
 
S

sternr

Oh no... once you have the Type, don't convert it to a name (string) and
back again.

Use Activator.CreateInstance instead, or Type.GetConstructor and call its
Invoke method

Hey Ben,
Why using Assembly.CreateInstance(typeName) is not good?

Thanks

--sternr
 
J

Jon Skeet [C# MVP]

Why using Assembly.CreateInstance(typeName) is not good?

It just seems a bit pointless to use a string representation when the
Type is already there. Why ask the framework to go through parsing the
name etc when you can use the Type object directly?

Jon
 
M

Marc Gravell

Just another thought...

In this type of (factory?) scenario, I tend to create a
SomeMethod<T>(...) with the appropriate args and conditions (such as
new()), and then instead of using lots of reflection (invoke ctor, set
properties, call methods, etc), I like to use:
GetMethod({name}).MakeGenericMethod({type(s)}).Invoke({args})
to invoke SomeMethod<TWhatever> for my *specific* type instance(s);
only 1 reflection invoke, and once inside SomeMethod you have full
compile-time safety.

A little messy to invoke initially (especially if you get lots of Ts),
but works very well, and has saved me more than once (i.e. where a
change causes a line in SomeMethod to break at compile-time, rather
than blowing up at run-time).

Marc
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top