mohammad
mohammad

Reputation: 1318

create exact instance from class name

i have two classes: Class1 and Class2

class Class1
{
    public void method();
}

class Class2
{
    public void method();
}

in another place I have the class type and I want to create an instance from it. type is typeof(Class1) or typeof(Class2)

public void CreateInstance(Type type)
{
    var instance = Activator.GetInstance(type);
    instance.method(); //compile error: object doesn't contain method
}

a solution is I define an interface that my classes implement that interface.

interface IInterface
{
    void method();
}

public void CreateInstance(Type type)
{
    var instance = Activator.GetInstance(type);
    ((IInterface)instance).method();
}

because I can't access to class definition I can't do this. How can I do this?

Upvotes: 0

Views: 79

Answers (3)

Panagiotis Kanavos
Panagiotis Kanavos

Reputation: 131180

You can avoid reflection and performance issues entirely by using a generic method and dynamic:

public void CreateInstance<T>() where T:new()
{
    dynamic instance=new T();
    instance.method();
}

Which you can call simply by passing the type:

CreateInstance<Class1>();
CreateInstance<Class2>();

Type safety is lost either when using reflection or using dynamic. Checking for the existence of a method with reflection isn't any safer or less risky than having the runtime throw an exception - in both cases you have to handle an exceptional condition. What are you going to do when this exception occurs?

With dynamic, a missing method will raise a RuntimeBinderException specifying that a method is missing. If I changed the method call from method to method1 I'll get an exception saying:

'ConsoleApplication24.Class1' does not contain a definition for 'method1'

This way the code does not pay the reflection penalty for the normal cases. This is also safer - there is no way that the exception can be missed.

The only way that provides compile-type safety is to have the classes implement an interface and use it as a generic constraint, eg:

public static void CreateInstance<T>() where T : ISomething, new()
{
    var instance = new T();
    instance.method();
}

Upvotes: 1

Michal Dymel
Michal Dymel

Reputation: 4360

Best option would be to use interface for safety. But if you can't do that, you can invoke this method through reflection:

public class MyClass
{
    public void Method()
    {
        Console.WriteLine("executed");
    }
}

public class MyActivator
{
    public static void CreateInstance(Type type)
    {
        var instance = Activator.CreateInstance(type);

        var method = GetMethod("method");
        method.Invoke(instance, null);
    }
}

And then you call this by:

MyActivator.CreateInstance(typeof(MyClass));

Remember to add some checking if method is not null

Upvotes: 0

Enigmativity
Enigmativity

Reputation: 117019

This is what you need:

public void CreateInstance(Type type)
{
    var instance = Activator.CreateInstance(type);
    type.GetMethod("method").Invoke(instance, null);
}

Or, alternatively, use dynamic:

public void CreateInstance(Type type)
{
    dynamic instance = Activator.CreateInstance(type);
    instance.method();
}

NB: You had GetInstance instead of CreateInstance in your code, but I corrected it.

Upvotes: 4

Related Questions