ObjectType
ObjectType

Reputation: 1217

Type identifiers at runtime

The following isn't possible.

var dataType = Type.GetType("System.String");

//magic here

var hs = new HashSet<dataType>();

The above result in the error: The type or namespace name 'dataType' could not be found (are you missing a using directive or an assembly reference?)

Is there some magic in the middle to make it work? If not, what are workable approaches to achieve the intended goal? Thank you.

Edit: Was trying to be helpful by being brief, but I need to provide more detail.

Let's say we have something like this:

public static T Deserialize<T>(string json)
{
    var serializer = new JavaScriptSerializer();
    return serializer.Deserialize<T>(json);
}

And let's assume the serialized object type was stored as a string. How do we deserialize with the type as a string. I have a few work arounds in mind, but was hoping there was something involving runtime type identifiers I was unfamiliar with.

Upvotes: 0

Views: 1133

Answers (3)

Lawrence
Lawrence

Reputation: 3297

Given that @Marc Gravell didn't suggest this I'm guessing there is something wrong with this, but you could try something like this:

public class HashSetGenerator
{
    public static HashSet<T> GetHashSet<T>(T testType) 
    {
        return new HashSet<T>();
    } 
}

You can then generate the HashSet like this:

public static void Main(string[] args)
{
    HashSet<string> stringHash = HashSetGenerator.GetHashSet("string");
    HashSet<int> intHash = HashSetGenerator.GetHashSet(123);
}

Upvotes: 0

Jesse C. Slicer
Jesse C. Slicer

Reputation: 20157

Best I think you can do is:

var dataType = Type.GetType("System.String");

// This is your magic.
var hst = typeof(HashSet<>).MakeGenericType(dataType);
var hs = (IEnumerable)Activator.CreateInstance(hst);  
var add = hst.GetMethod("Add");

(IEnumerable being the only sorta useful non-generic interface implemented by HashSet<T>)

now, add items:

add.Invoke(hs, new object[] { "Test 1" });
add.Invoke(hs, new object[] { "Test 2" });
add.Invoke(hs, new object[] { "Test 3" });
add.Invoke(hs, new object[] { "Test 1" });

So you can foreach over it, but it's still pretty useless as you get back objects again. You could then possibly try dynamic and duck-type the item:

foreach (dynamic item in hs)
{
    // item.Length would work here, for instance.
}

Upvotes: 1

Marc Gravell
Marc Gravell

Reputation: 1062770

The closest you can get to that is:

object hs = Activator.CreateInstance(
       typeof(HashSet<>).MakeGenericType(dataType));

However, this is really hard to use - there is no particularly usable non-generic API exposed by HashSet<T>, so I would consider thinking about what you want to do.

Upvotes: 2

Related Questions