CreateInstance InvalidCastException - PullRequest
       1

CreateInstance InvalidCastException

0 голосов
/ 19 ноября 2018

В моем базовом приложении .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 голосов
/ 20 ноября 2018

Примечание: я думаю, что OP пытается создать что-то вроде плагина. Если так, есть много пользовательских библиотек, для которых я предлагаю вам использовать уже реализованные вещи, а не создавать колесо самостоятельно

Это довольно распространенная ошибка, когда люди впервые начинают играть со сборками во время выполнения. Это было сделано :) Проблема в том, что вы используете Assembly.LoadFile для загрузки вашей сборки в домен приложения. Не вдаваясь в подробности, даже если вы загрузите одну и ту же dll с помощью Assembly.LoadFile, типы, определенные в сборке, будут обрабатываться по-разному. Допустим, у меня есть сборка 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.

Вот очень хорошее и подробное объяснение. Лучшие практики

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...