Search code examples
c#dll-injectionactivator

Activator.CreateInstance with custom class argument


I am trying to create a instance(Class Test) from dll by using Activator.CreateInstance.

Class Test has one constructor which requires a arguement Class CommonService. But it throw System.MissingMethodException error.

There is the code:

// Define
public class Test: BaseTest
{
    public Test(CommonService commonService) : base(commonService, new TestConfigurations()
    {
       enableTimer = false
    })
    { 
    }
}

// Usage
var commonService = new CommonService();
var test = new Test(commonService); // test can be created successfully.

var dll = Assembly.LoadFile(@"xxx\Test.dll");
foreach (Type type in DLL.GetExportedTypes())
{
    if (type.BaseType?.Name?.Equals("BaseTest") == true)
    {
        dynamic c = Activator.CreateInstance(type, new object[] { // Throw System.MissingMethodException error
            commonService
        });
    }
}

Here is the full code link: https://codeshare.io/2EzrEv

Is there any suggestions about how to solve the problem?


Solution

  • The Activator.CreateInstance as shown: should work just fine. If it isn't, then the type you're initializing might not be what you think it is - check the value of type.FullName. Alternatively, it is possible that you have types by the same name in different locations, meaning: the CommonService that you're passing in is not the same as the CommonService that the type is expecting. You can check that with reflection. The following prints True twice:

    using System;
    using System.Linq;
    using System.Reflection;
    
    public class Test : BaseTest
    {
        public Test(CommonService commonService) : base(commonService, new TestConfigurations()
        {
            enableTimer = false
        })
        {
        }
    }
    
    static class P
    {
        static void Main()
        {
            // Usage
            var commonService = new CommonService();
            var test = new Test(commonService); // test can be created successfully.
    
            var type = typeof(Test); // instead of loop
            dynamic c = Activator.CreateInstance(type, new object[] { // Throw System.MissingMethodException error
                commonService
            });
            Console.WriteLine(c is object); // it worked
    
            var ctor = type.GetConstructors().Single();
            var ctorArg = ctor.GetParameters().Single();
            Console.WriteLine(ctorArg.ParameterType == typeof(CommonService)); // check the expected param type
        }
    }
    public class CommonService { }
    public class TestConfigurations
    {
        internal bool enableTimer;
    }
    public class BaseTest
    {
        public BaseTest(CommonService svc, TestConfigurations cfg) { }
    }