mardi 8 mars 2016

Create instance of class by string, but take implicit conversions into account - C# Reflection

I am in a situation where I need to create an object instance given a Type (as a string), and an array of constructor arguments.

This is how I achieve that:

public object Create(string Name, params object[] Args)
{
    return Activator.CreateInstance(Type.GetType(Name), Args);
}

This works fine in most cases, but there is a problem with it; it doesn't take implicit conversions into account.


Let me explain what I mean, say we have a simple class with an implicit conversion to int defined

public class ImplicitTest
{
    public double Val { get; set; }

    public ImplicitTest(double Val)
    {
        this.Val = Val;
    }

    public static implicit operator int(ImplicitTest d)
    {
        return (int)d.Val;
    }
}

and we have a class that uses an int as it's constructor's parameter

public class TestClass
{
    public int Val { get; set; }        

    public TestClass(int Val)
    {
        this.Val = Val;
    }
}

Now say we want to make an instance of TestClass, we can do: new TestClass(5). In this case, we use the exact parameter type, that the constructor specifies (int). However we can also create an instance of the class using our ImplicitTest class, as such: new TestClass(new ImplicitTest(5.1)). This works, because the parameter is implicitly converted from ImplicitTest to int. Activator.CreateInstance() however does not do this.


We can use our Create(string Name, params object[] Args) method from before to make an instance of TestClass as such: Create("ThisNamespace.TestClass", 5), this works. The problem I am experiencing is that trying to use implicit conversions does not work, therefore this snippet throws an error: Create("ThisNamespace.TestClass", new ImplicitTest(5.1))

I have absolutely no idea how take this into account, but it is important for my use case. Maybe there is some parameter of the Activator.CreateInstance() function I am missing, or maybe there is a completely different method I can use to achieve my goal? I have not been able to find any answers.


TL;DR

//Valid
new TestClass(5);

//Valid
new TestClass(new ImplicitTest(5.1));

//Valid
Activator.CreateInstance(Type.GetType("ThisNamespace.TestClass"), 5); 

//Invalid, throws System.MissingMethodException
Activator.CreateInstance(Type.GetType("ThisNamespace.TestClass"), new ImplicitTest(5.1)); 

Why?





Aucun commentaire:

Enregistrer un commentaire