Динамически загружать DLL из определенной папки? - PullRequest
3 голосов
/ 19 января 2012

На данный момент у меня есть этот код:

var shellViewLibrary = Assembly.LoadFrom(Path.Combine(_DllsPath, _DllShellView));
IEnumerable<Type> types = shellViewLibrary.GetTypes();

foreach (Type type in types)
{
    var typeIShellViewInterface = type.GetInterface(_NamespaceIShellView, false);
    if (typeIShellViewInterface != null)
    {
        //here
    }
}

Дело в том, что там, где я получил //here, я хочу использовать Activator.CreateInstance для создания объекта, тип которого type , в определенной папке (то есть вне папки сборки) Я пробовал около 20 разных вещей, большинство из них с этим: http://msdn.microsoft.com/en-us/library/d133hta4.aspx но никто не работает ... Типичная вещь, которую я попробовал:

object MyObj = Activator.CreateInstance(shellViewLibrary.FullName, type.FullName);

или

object MyObj = Activator.CreateInstance(Path.Combine(_DllsPath, _DllShellView), type.FullName);

Я всегда получал разные исключения, наиболее распространенным из которых было:

XamlParseException

Мне кажется, что я неправильно использую Activator.CreateInstance с двумя параметрами. Что мне делать?

Ответы [ 5 ]

8 голосов
/ 19 января 2012

Это пример «Динамической загрузки .dll из определенной папки» во время выполнения.

// Check if user has access to requested .dll.
string strDllPath = Path.GetFullPath(strSomePath);
if (File.Exists(strDllPath))
{
    // Execute the method from the requested .dll using reflection (System.Reflection).
    Assembly DLL = Assembly.LoadFrom(strDllPath);
    Type classType = DLL.GetType(String.Format("{0}.{1}", strNmSpaceNm, strClassNm));
    if (classType != null)
    {
        // Create class instance.
        classInst = Activator.CreateInstance(classType);

        // Invoke required method.
        MethodInfo methodInfo = classType.GetMethod(strMethodName);
        if (methodInfo != null)
        {
            object result = null;
            result = methodInfo.Invoke(classInst, new object[] { dllParams });
            return result.ToString();
        }
    }
}

Мне потребовалось некоторое время, чтобы потренироваться, поэтому я надеюсь, что это пригодится ...

7 голосов
/ 19 января 2012

Как только вы позвоните по этой линии

var shellViewLibrary = Assembly.LoadFrom(Path.Combine(_DllsPath, _DllShellView)); 

Сборка загружена в память. До тех пор, пока вы правильно указали типы из этого, вы сможете использовать Activator.CreateInstance для создания типов. т.е.: нет необходимости дополнительно указывать , где тип.

Относительно Активатора, с MSDN метод CreateInstance может принимать System.Type. Я бы просто использовал этот метод внутри вашего оператора if:

Activator.CreateInstance(Type type);

Что бы я попытался сделать для отладки, это сначала создать тип, а затем передать его в CreateInstance. Вы можете обнаружить, что создание самого типа не выполняется (из-за неразрешенной сборки) или создается экземпляр этого типа (из-за исключения в конструкторе). На первый взгляд ваш код здесь выглядит правильно:

foreach (Type type in types)      
{          
    var typeIShellViewInterface = type.GetInterface(_NamespaceIShellView, false);          
    if (typeIShellViewInterface != null)          
    {              
        try
        {
            // I assume you are calling this line at the point marked 'here'. 
            // To debug the creation wrap in a try-catch and view the inner exceptions
            var result = Activator.CreateInstance(type);          
        }
        catch(Exception caught)
        {
            // When you hit this line, look at caught inner exceptions
            // I suspect you have a broken Xaml file inside WPF usercontrol
            // or Xaml resource dictionary used by type
            Debugger.Break();
        }
    }      
}  

В своем вопросе вы указываете, что получаете XamlParseException. Мне кажется, что рассматриваемый тип - это UserControl (или иным образом относится к файлу ресурса XFL WPF), и в этом файле Xaml есть ошибка, то есть ничего общего с использованием Assembly.Load или Activator.CreateInstance.

Не могли бы вы опубликовать внутреннее исключение (я), чтобы лучше понять, в чем проблема?

2 голосов
/ 19 января 2012

Проверьте MEF и Prism .MEF - это библиотека внедрения зависимостей, которая помогает с этим.Вы можете загрузить все свои зависимости из определенной папки и динамически загружать их.

Prism - это шаблон, который использует внедрение зависимостей и прекрасно работает с MEF для динамической загрузки библиотек

0 голосов
/ 19 января 2012

Я не уверен, что вы подразумеваете под этим:

создать объект с типом тип в определенной папке (которая находится вне папки сборки)

Тип существует только в сборке. Путь не имеет никакого отношения к типам в .NET

Я предполагаю , что под «путем» вы действительно подразумеваете «пространство имен», то есть вы не знаете, в каком пространстве имен существует тип. Вы уже загрузили сборку в свой код. Осмотрите сборку, используя отражение, чтобы найти тип, который вы ищете. Затем передайте объект Type, представляющий тип, который вы ищете, Activator.CreateInstance

0 голосов
/ 19 января 2012

Если вы пытаетесь создать тип с помощью класса Activator из библиотеки DLL, которая находится за пределами вашего приложения, вам необходимо сначала загрузить эту библиотеку DLL внутри домена приложения.Самый простой и быстрый способ сделать это - использовать метод Assembly.LoadFile .

Более подробную информацию об этом методе можно найти здесь: http://msdn.microsoft.com/en-us/library/system.reflection.assembly.loadfile.aspx

Когдасборка загружена правильно, вы можете использовать Активатор для создания экземпляра из типа внутри DLL.Мы используем эту механику для запуска пользовательского кода в нашем приложении.

...