Отражение - не могу создать новый экземпляр объекта C # - PullRequest
0 голосов
/ 14 октября 2010

Я пытаюсь создать подключаемый модуль типа archetecure для своего проекта. Мне бы хотелось иметь возможность загружать сборку, получать тип, производный от абстрактного базового класса в моем проекте, создавать его экземпляры и загружать этот производный тип в основной объект обработки.

Моя проблема сейчас заключается в том, что когда я создаю экземпляр объекта из отраженной сборки, он всегда равен нулю. Я чувствую, что проблема может заключаться в том, что у ссылочной сборки есть сторонние dll, которые она использует. Вот код: единственное исключение, которое получает удар, является последним.

static void Main(string[] args)
{
    string engineFilePath = ConfigurationManager.AppSettings["EngineFilesDirectory"]
        + "\\" + ConfigurationManager.AppSettings["EngineDllFileName"];
    Assembly asm = Assembly.LoadFile(engineFilePath);

    Type engineType = asm.GetType(ConfigurationManager.AppSettings["EngineType"]);

    if (!engineType.IsSubclassOf(typeof(EngineConcrete)))
    {
        throw new ArgumentException("Engine is not derived from base implimentation.");
    }

    object engineInstance = asm.CreateInstance(engineType.Namespace + "." + engineType);


    if (engineInstance == null)
    {
       //always thrown at this point
        throw new Exception(string.Format("Engine object is null."));
    }

    return;
}

Если я изменяю строку экземпляра на Activator.CreateInstance(engineType), я получаю сообщение об ошибке, в котором говорится, что один из сторонних dll, на который ссылается отраженная сборка, не может быть найден, хотя они находятся в том же каталоге, что и DLL отражение.

Существует открытый конструктор для типа, который также отражается. Он не имеет параметров и наследуется от класса EngineConcrete.

Ответы [ 3 ]

1 голос
/ 14 октября 2010

Я думаю, что null - это то, что вы получаете, когда тип не может быть найден; имя пространства имен плюс имя типа может быть недостаточным (серьезные проблемы с именами). Что произойдет, если вы поместите сторонние dll в каталог исполняемого приложения, а не в каталог плагина?

1 голос
/ 14 октября 2010

Это ошибка: engineType.Namespace + "." + engineType - это выражение оценивается в "The.Namespace.The.Namespace.Type" вместо "The.Namespace.Type".Либо используйте engineType.FullName или Activator.CreateInstance класс и используйте engineType напрямую.

Обновление: обратите внимание, что MSDN говорит «… или ноль, если typeName не найдено». О возвращаемом значении Assembly.CreateInstance.

0 голосов
/ 14 октября 2010

Проблема заключается в том, что CLR не находит сторонние сборки, так как они не находятся в проверяемой папке.

Вы можете добавить обработчик события для события AppDomain.CurrentDomain.AssemblyResolve для обработки этих случаев. Ниже приведен пример реализации, которая работала для меня, когда сборки динамически загружались из папки «Plugins», которая содержится в папке bin:

class Program
{
    static string _PluginDirectory;
    static string PluginDirectory
    {
        get
        {
            if (_PluginDirectory == null)
            {
                _PluginDirectory = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), @"Plugins");
            }
            return _PluginDirectory;
        }
    }

    static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
    {
        AssemblyName assemblyName = new AssemblyName(args.Name);
        return Assembly.LoadFile(System.IO.Path.Combine(PluginDirectory, assemblyName.Name + ".dll"));
    }

    static void Main(string[] args)
    {
        AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);

        var asm = Assembly.LoadFile(System.IO.Path.Combine(PluginDirectory, @"Plugin.dll"));

        var transmogrifier = asm.CreateInstance("Plugin.ConcreteTransmogrifier") as Common.Transmogrifier;

        if (transmogrifier != null)
        {
            Console.WriteLine(transmogrifier.Transmogrify("Wowzers!"));
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...