0

Is there any way to achieve something like this?

If "Employee" is passed as an argument to a method it should return an object of type Employee.

But without using reflection.

Zenexer
  • 18,788
  • 9
  • 71
  • 77
NIlesh Lanke
  • 1,213
  • 9
  • 26
  • 35
  • reflection would help. the question is: why? – vulkanino Feb 09 '12 at 14:41
  • You're not going to do it without reflection. That's what reflection _is_, in simple terms: associating names/metadata with code. Why in heck would you want to do it without reflection? That's like asking how to open a door without opening a door. – Zenexer Feb 09 '12 at 14:58
  • possible duplicate of [How do I create an instance from a string in C#?](http://stackoverflow.com/questions/648160/how-do-i-create-an-instance-from-a-string-in-c) – Krizz Feb 09 '12 at 15:05
  • @Krizz This question differs quite drastically in that he doesn't want to use reflection. A question worth answering--or rather, explaining why it can't be answered. – Zenexer Feb 09 '12 at 15:12
  • @Zenexer - true, haven't noticed an edit adding this constraint. – Krizz Feb 09 '12 at 15:19
  • 1
    dont forget to mark answer as accpeted if you got the info you want – Pranay Rana Feb 09 '12 at 15:43

6 Answers6

2

You could use Type.GetType(string) to get the meta data for the type. However, this requires an Assembly Qualified Name of the type unless the type resides in the currently executing assembly or is part of mscorlib.dll.

Then you can use Activator.CreateInstance(Type) to obtain an instance.

var type = Type.GetType(typeName);
var obj = Activator.CreateInstance(type);

At this point, the static type of obj is System.Object. You would need to continue using reflection to get at the properties and methods defined on your actual type, or you could treat the object as dynamic, assuming you don't know at compile time what class to cast the result to (and if you did know, you would skip this entire process).


Edit: With your added constraint of not wanting to use reflection, this changes your options. The code will not be quite as dynamic in regards to what you can support, you will generally need to have an idea ahead of time, but that might be a good thing, depending on what you are trying to accomplish. What you might have is simply a switch statement or a dictionary that has supported types, keying on the name as a string.

public object GetInstanceOf(string typeName)
{
    switch (typeName)
    {
        case "Employee": return new Employee();
        case "Manager" : return new Manager();
        case "Owner" : return new Owner();
        // etc
        default: 
            throw new InvalidOperationException("typeName is not supported");
    }
}

Notice with this approach, you know all of your supported types in advance. There are other ways to know the types in advance outside of code (ex: configuration, data), but those would generally get you back into the land of the first part of the answer. Also note that your return type is still limited. It must be a common base type or interface for the classes involved. In my code sample, it's the common base type for all classes and structs, System.Object. For you, this might be more of a factory, with a Worker base class or IWorker interface. Or maybe Employee is the base and your method is constructing specialized children of it. The latter two examples give you compile-time access to the base or interface defined methods and properties.

Anthony Pegram
  • 123,721
  • 27
  • 225
  • 246
  • Question: why do some answers here use CreateInstance() directly with a string and some go for the Type object first? – Andrew Barber Feb 09 '12 at 14:48
  • They're using a [different overload](http://msdn.microsoft.com/en-us/library/d133hta4.aspx) that accepts `(string assemblyName, string typeName)`. Under the covers, it is likely doing the same thing, using the parameters to construct an assembly qualified reference to get the type metadata. Or perhaps it's doing something different with the end result being the same. – Anthony Pegram Feb 09 '12 at 14:50
  • Cool; I was mostly wondering if there was an immediate, substantive difference in the approaches. This isn't something I've ever had to do myself, so I wasn't sure. – Andrew Barber Feb 09 '12 at 14:52
1

Yes than you can do with the help of "Reflection"

Try

Employee employee =(Employee)Activator.CreateInstance("Employee"); 

check @jon skeet answer : How do I create an instance from a string in C#?

Community
  • 1
  • 1
Pranay Rana
  • 175,020
  • 35
  • 237
  • 263
1

Instantiating an Arbitrary Type Without Reflection

I was wrong. There are a lot of ways that you can instantiate a type without true reflection, it would seem. I'll try to compile a list of all that I can find.

Generics

Depending on what you are trying to do, you might be able to do a very cool technique called generics. You can't input an arbitrary name of a type at runtime, so this doesn't necessarily answer your question in full, but if you know the types that you want at compile time, this makes for a great tool. This involves no reflection of any sort, but is entirely compile time. Here's an example:

interface IParsable
{
    bool TryParse(string text);
}

class MyInt : IParsable
{
    public int Value { get; private set; }

    public static MyInt Parse(string text)
    {
        Parser parser = new Parser();
        return parser.Parse<MyInt>(text);
    }
}

class MyFloat : IParsable
{
    public float Value { get; private set; }

    public static MyFloat Parse(string text)
    {
        Parser parser = new Parser();
        return parser.Parse<MyFloat>(text);
    }
}

class Parser
{
    // The "new()" constraint means that T must have a
    // parameterless constructor.
    private T Parse<T>(string text)
        where T : IParsable, new()
    {
        // Even though T isn't actually a type, we can use
        // it as if it were, for the most part.
        T obj = new T();

        // Because we had the IParsable constraint, we can
        // use the TryParse method.
        if (!obj.TryParse(text))
        {
            throw new Exception("Text could not be parsed.");
        }

        return obj;
    }
}

Dictionary of Lambdas

Credit to Anthony Pegram for his genius on this one (see comments below). Previously I had this using reflection, but he fixed it to work without any reflection whatsoever, thanks to lambda expressions.

static readonly IDictionary<string, Func<object>> Types = new Dictionary<string, Func<object>>()
{
    { "TypeA", () => new TypeA() },
    { "TypeB", () => new TypeB() },
    { "TypeC", () => new TypeC() },
};

// If you're okay with a bit of reflection behind-the-scenes, change "object"
// here to "dynamic", and you won't have to cast down the road.
object void GetInstance(string name)
{
    if (Types.ContainsKey(name))
    {
        return Types[name]();
    }
    else
    {
        return null;
    }
}

Pre-Instantiated Objects

Yet another option would be to return the same reference each time. This avoids "true" reflection altogether. This idea of reusing instances has some important implications, which could be either good or bad, depending on what you are doing. These implications are very interesting, and can be quite amazing if used properly.

You could, if you wanted, have each type implement a specific interface, and cast to that, instead of returning a raw object.

static readonly IDictionary<string, object> Instances = new Dictionary<string, object>()
{
    { "TypeA", new TypeA() },
    { "TypeB", new TypeB() },
    { "TypeC", new TypeC() },
};

object void GetInstance(string name)
{
    if (!Instances.ContainsKey(name))
    {
        return null;
    }

    return Instances[name];
}

Instantiating an Arbitrary Type With Reflection

You've got a nice array of answers that will work great if your type has a parameterless constructor. But what if it doesn't?

const string TYPE = "System.String";
Type type = Type.GetType(TYPE);
if (type == null)
{
    // Type doesn't exist--at least, not in mscorlib or current assembly,
    // or we didn't specify the assembly.
    throw new Exception("Could not find type " + TYPE + ".");
}

// Note the Type array.  These are the types of the parameters that the
// constructor takes.
ConstructorInfo ctor = type.GetConstructor(new Type[] { typeof(char), typeof(int) });
if (ctor == null)
{
    // Constructor doesn't exist that takes those parameters.
    throw new Exception("Could not find proper constructor in " + TYPE + ".");
}

// Note the object array.  These are the actual parameters passed to the
// constructor.  They should obviously match the types specified above.
string result = (string)ctor.Invoke(new object[] { 'a', 5 });
nawfal
  • 70,104
  • 56
  • 326
  • 368
Zenexer
  • 18,788
  • 9
  • 71
  • 77
  • 1
    Note you could also have a dictionary approach with `Dictionary>`, where you could do `dictionary.Add("Foo", () => new Foo());`. This allows you to have `return dictionary[typeName]();`, thereby another way to eliminate using type metadata while also always generating a new instance. – Anthony Pegram Feb 09 '12 at 17:42
  • Wow, nice one, @AnthonyPegram. I never would've thought of that. I hope you don't mind, but I edited that in, since it's such a great idea. – Zenexer Feb 09 '12 at 17:56
  • That's fine. Incorporating comments when useful is very much fair game. – Anthony Pegram Feb 09 '12 at 17:58
  • I dont understand your 2nd approach at all (generics one). If I have `T` type parameter, then what's all the hassle about? OP has just string (even then I think you complicated the design. What your `IParsable` needs is just `string Name { get; set; }`). And hope you know `new T()` does use reflection behind the scenes technically, and is slower. Here's a relevant link http://stackoverflow.com/questions/6069661/does-system-activator-createinstancet-have-performance-issues-big-enough-to-di. Apart from the generics one, good answer! – nawfal Jun 12 '13 at 19:37
  • @nawfal Where did you get that `new T()` uses reflection? It shouldn't. If you have any doubt about this, compile a test application, and disassemble it to MSIL. – Zenexer Jun 13 '13 at 03:51
  • @Zenexer I gave you a link to find it. Here's a more [direct one](http://stackoverflow.com/questions/367577/why-does-the-c-sharp-compiler-emit-activator-createinstance-when-calling-new-in). And [Jon's take](https://msmvps.com/blogs/jon_skeet/archive/2011/08/22/optimization-and-generics-part-1-the-new-constraint.aspx) on it. – nawfal Jun 13 '13 at 04:13
  • 1
    @nawfal Interesting. I tend to specify constraint that restricts it to either a value or reference type, so I suppose that's why I've never seen this. In any case, it's easy to avoid using constraints. – Zenexer Jun 15 '13 at 10:57
0

You could use Activator.CreateInstance()

Employee employee =(Employee)Activator.CreateInstance("Namespace", "Employee");
Gabe
  • 49,577
  • 28
  • 142
  • 181
0

Using reflection as @vulkanino says you will end with something like this:

Employee instance = (Employee)Activator.CreateInstance("MyNamespace.Employee, MyAssembly");

Hope this helps you.

Diego
  • 1,531
  • 1
  • 15
  • 27
0

Using reflection you can find types in assemblies, whether it be the executing assembly or other loaded ones (you may load them on demand, actually). Without specifying a complete example of how this might work in your scenario, you would then use something along the lines of Activator.CreateInstance to create instances of your found objects.

Grant Thomas
  • 44,454
  • 10
  • 85
  • 129