CreateInstance InvalidCastException

时间:2018-11-19 17:15:47

标签: c# reflection

.net核心应用程序中包含三个版本。

Solution.Models.Customer:

public class Customer : ICustomer
{           
    public void Get()
    {
        Console.WriteLine("Message!");
    }
}

Solution.Interfaces.ICustomer:

public interface ICustomer
{
    void Get();
}

Solution.Creator.ContainerCreator:

public class ContainerCreator
{
    Assembly _assembly;

    public void Add(Assembly assembly)
    {
        _assembly = assembly;
    }

    public object CreateInstance(Type type)
    {
        object instance;

        var classesInfo = GetClassesInfo();
        //classes Info looks for a match in the assembly with the passed parameter.
        var result = classesInfo.Where(w => w.ClassType.FullName == type.FullName).FirstOrDefault();

        var objectType = result.ClassType;

        instance = Activator.CreateInstance(objectType);

        return instance;
    }
}

然后,当我创建类型为( ICustomer )的对象时,会成功创建 ,但是如果我强制转换为( Customer >)类型,则发生异常- System.InvalidCastException

var files = Directory.GetFiles(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),
                "Solution.Models.dll",
                SearchOption.TopDirectoryOnly);

var asm = Assembly.LoadFile(files[0]);

ContainerCreator containerCreator = new ContainerCreator();

containerCreator.Add(asm);
// Success
Customer = (ICustomer)containerCreator.CreateInstance(typeof(Customer));
// System.InvalidCastException
//Customer = (Customer)containerCreator.CreateInstance(typeof(Customer));

我在做什么错,我该如何打败这个例外?

1 个答案:

答案 0 :(得分:1)

注意:我认为OP正在尝试创建某种插件。如果是这样,我建议您使用许多自定义库,而不是自己创建轮子,而是使用已经实现的东西

当人们在运行时第一次开始使用程序集时,这是一个非常常见的错误。到那儿去了吗:)问题是您正在使用Assembly.LoadFile将程序集加载到您的应用程序域中。无需赘述,即使您使用Assembly.LoadFile加载相同的dll,程序集中定义的类型也将被视为不同。假设我有程序集A

../MyFolder/A.dll
     public class MyType;
     public class MyAnotherType;
     ....

 var aDll = Assembly.LoadFile("A.dll");
 var aDllAgain = Assembly.LoadFile("A.dll");
 var myTypeFromADll =aDll.GetType("MyType");
 var myTypeFromADllAgain = aDllAgain.GetType("MyType");

 //Yes this is of type MyType but since you used LoadFile
 //It is of type MyType from a_dll code base
 var instanceFromADll = Activator.CreateInstance(myTypeFromADll);

 //Yes this is of type MyType but since you used LoadFile
 //It is of type MyType from a_dll_again code base
 var instanceFromADllAgain = Activator.CreateInstance(myTypeFromADllAgain);

因此,您正在获取InvalidCastException,因为您试图将X类型的实例转换为Y类型。

解决方案很简单。您应该使用Assemly.Load方法,如果不能,那么请使用Assembly.LoadFrom。除非您完全知道自己在做什么,否则请远离Assembly.LoadFile

这里是一个很好的详细解释。 Best practices