views:

99

answers:

2

I'm trying to dynamically create an object of a certain type in a LINQ-to-XML query based on a string within my XML document. I'm used to being able to dynamically create an object of any type in PHP and JavaScript by simply being able to write something like:

$obj = new $typeName();

Ideally, I'd like to be able to do something like:

List<someObj> = (from someObjs in XMLfile
                 select new someObj()
                 {
                     Name = (string)someObjs.Element("name"),
                     NestedObj = new someObjs.Element("nestedObj").Element("type")()
                     {
                         NestedName = (string)someObjs.Element("nestedObj").Element("name")
                     }
                 }).ToList();

I just can't figure out how to do it without grabbing a hold of the current executing assembly.

+8  A: 

You can use:

Activator.CreateInstance(Type.GetType(typeName))

Of course, this only works for types with a parameterless constructor.


Update (initializing the object):

You can use C# 4 dynamic typing features to set properties of the newly created object:

dynamic newObj = Activator.CreateInstance(Type.GetType(typeName));
newObj.NestedName = str;

In the context of a LINQ to XML query, you may have to resort to lambda syntax with explicit body:

var list = XMLFile.Select(someObjs => {
    dynamic nestedObj = Activator.CreateInstance(
       Type.GetType(someObjs.Element("nestedObj").Element("type")));
    nestedObj.NestedName = (string)someObjs.Element("nestedObj").Element("name");
    return new someObj {
        Name = (string)someObjs.Element("name"),
        NestedObj = nestedObj
    };
}).ToList();
Mehrdad Afshari
Something to keep in mind: Afaik `typeName` must also state the assembly name if the type isn't in mscorlib or the ExecutingAssembly.
dtb
You can call `Type.GetType(string)` and then use that type with the other `Activator.CreateInstance` overloads.
Jim Schubert
@Jim: Added your suggestion to the answer.
Mehrdad Afshari
@dtb: I think you always have to mention the assemblyName when calling `Activator.CreateInstance` directly. I mistakenly thought it has an overload that takes a single string but it doesn't.
Mehrdad Afshari
Could I use shortcut initialization after? Like, say, Activator.CreateInstance(Type.GetType(typeName)){ Name = someValue } I ask only because since the object in question is nested within another, that's the easiest way to initialize it.
kevinmajor1
@kevinmajor1: Since C# is a statically typed language and you don't know the actual type you are instantiating at compile time, you are directly limited to calling methods defined on object. You can, however, assign the returned value by `CreateInstance` to a `dynamic` variable and set a property. I'll add this to my answer.
Mehrdad Afshari
Awesome. Exactly what I needed. I'd upvote multiple times if I could.
kevinmajor1
+3  A: 

Use the createinstance method of activator class

Gregoire