Activator.CreateInstance not working for implicit cast scenario
Asked Answered
P

1

0

I'm trying to use Activator.CreateInstance Method to dynamically create a new instance. But when I pass the instance of a class that is implicitly castable to the actual type (in constructor), I get the System.MissingMethodException. Here is my testing code that I'm using to verify :

    using System;

    namespace ActivatorTest1
    {
        class Program
        {
            static void Main(string[] args)
            {
                Test t = new Test(new string[] { "abc" });
                NewClass nc = new NewClass(new SubTest("apple"));
                NewClass2 nc2 = nc;
                try
                {
                    Object[] paramList = new object[] { nc }; // nc is an instance of NewClass, which is implicitly castable to NewClass2
                    Activator.CreateInstance(typeof(Test), paramList);
                    Console.WriteLine("Instance successfully created");
                    Console.WriteLine("**************************");
                }
                catch (Exception exc)
                {
                    Console.WriteLine("INSTANCE CREATION FAILED FOR IMPLICIT CASTING SCENARIO. \r\n\r\n " + exc);
                }

                Console.WriteLine("\r\n\r\n\r\n****************************************************\r\n\r\n\r\n");
                try
                {
                    Object[] paramList = new object[] { t }; // Although t is an instance of Test which is the base class for SubTest, MissingConstructorException is thrown
                    Activator.CreateInstance(typeof(NewClass), paramList);
                    Console.WriteLine("Instance successfully created");
                    Console.WriteLine("**************************");
                }
                catch (Exception exc)
                {
                    Console.WriteLine("INSTANCE CREATION FAILED FOR DERIVED CLASS SCENARIO. \r\n " + exc);
                }
                Console.ReadKey();
            }
        }

        class Test
        {
            public Test(string[] strArr)
            { }

            public Test(NewClass2 nc2)
            { }
        }

        class SubTest : Test
        {
            public SubTest(string str)
                : base(new string[] { str })
            { }
        }

        class NewClass // implicitly castable to NewClass2
        {
            public NewClass(SubTest st)
            { }
        }

        class NewClass2
        {
            public NewClass2()
            { }

            public static implicit operator NewClass2(NewClass nc)
            {
                return new NewClass2();
            }
        }
    }

Same thing occurs when I pass in a derived class instance(which is also in the code above). So, is this the expected behavior or I'm doing something wrong in my code. What would be the proper way out for this situation. Thanks.

EDIT: About the second part, my implementation is wrong(as mentioned in the answer below), and once the code was modified accordingly, the required instance is created using derived class as parameter successfully. BUT, about the implicit casting case, still a workaround is required. Maybe some patterns-related solution, or some tricky/hacky implementation, that would generate a new instance even for implicitly castable types?

Ptolemaic answered 5/1, 2014 at 9:55 Comment(0)
A
1

For the first scenario:

Activator.CreateInstance(typeof(Test), new object[] { new NewClass(...) });

This call fails because the class Test has no constructor taking one argument of type NewClass. Edit: You defined an implicit cast operator, but this is not working with the reflection approach of the Activator class as it is searching for a constructor on Test which takes an argument of type NewClass and this fails. Even if the creation via the new operator works (as the cast will be evaluated prior to the new operation). For the reflection, the compiler/clr does not know it needs to perform the cast because it only looks at the types.

Maybe you intended to call the ctor with NewClass2:

Activator.CreateInstance(typeof(Test), new object[] { new NewClass2(...) });

The second call fails because you need to pass an instance of SubTest and not Test. The other way would be okay (if the ctor needs Test and you pass SubTest).

Activator.CreateInstance(typeof(NewClass), new object[] { new SubTest(...) });

The MissingMethodException is right at this point because you are trying to call a constructor which isn't defined.

Anyaanyah answered 5/1, 2014 at 10:2 Comment(5)
About the base-derived class scenario, yes, you're right the instance is created successfully, after I modified the ctor accordingly. For the implicit casting scenario, unlike what you said, *Test t1 = new Test(new NewClass()); * compiles successfully.But only fails when creating instance through Reflection . If this is the desired way the Activator.CreateInstance works, then WHY would be my next question (a little explanation about the internal workings would be helpful).Ptolemaic
NewClass2 and NewClass aren't linker in any sense by inheritance, test has no ctor for NewClass, so the code you posted can't work. One second, i'll explain why...Anyaanyah
@Ptolemaic updated my answer- hope this clears things up for you.Anyaanyah
Thanks. Any idea, how to get around a situation of implicit casting ??? Maybe patterns-related solution, or some tricky/hacky implementation, that would generate a new instance even for implicitly castable types ???Ptolemaic
@Ptolemaic What about object[] paramList = new NewClass[] { ... }?Anyaanyah

© 2022 - 2024 — McMap. All rights reserved.