2013-09-22 3 views
6

Извинения за изворотливый вопрос - счастливы перефразировать, если у кого-то есть лучшее предложение.Как я могу динамически ссылаться на сборку, которая ищет другую сборку?

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

Следующий код PowerShell красиво работает для меня:

[Reflection.Assembly]::LoadFrom("C:\Program Files\Vendor\Product\ProductAPI.dll") 
$bobject = new-object ProductAPI.BasicObject  
$bobject.AddName("Some Name") 

Я изо всех сил, чтобы сделать то же самое в C#. Основываясь на других должностях на StackOverflow я в настоящее время это:

System.Reflection.Assembly myDllAssembly = 
System.Reflection.Assembly.LoadFile("C:\\Program Files\\Vendor\\Product\\ProductAPI.dll"); 

System.Type BasicObjectType = myDllAssembly.GetType("ProductAPI.BasicObject"); 

var basicObjectInstance = Activator.CreateInstance(BasicObjectType); 

Окончательные результаты линии в TargetInvocationException.

{ «Не удалось загрузить файл или сборку„AnotherObject, Version = 1.2.345.0, Culture = нейтрально, PublicKeyToken = нуль“или один из его зависимостей. Система не может найти указанный файл.»

Похоже, что конструктор BasicObject пытается вызвать AnotherObject (из AnotherObject.dll в той же папке), но не может его найти.

Любые советы о том, как обойти это?

+0

Я думаю, что DLL вы загружаете требует другого DLL для работы. Вы можете изучить зависимости DLL с помощью этого инструмента. http://www.dependencywalker.com/ – cgTag

+0

Когда вы найдете недостающую DLL. Скопируйте его в папку выпуска или измените Windows PATH, чтобы включить его. – cgTag

+0

Стоит проверить, что не загружается с помощью ['FUSLOGVW.exe'] (http://msdn.microsoft.com/en-us/library/e74a18c4.aspx) (* Assembly Binding Log Viewer *), который покажет вам, что не загружается (и где выглядит загрузчик .NET). – Richard

ответ

7

Если он не может найти зависимую сборку в the usual places, вам необходимо указать вручную, как их найти.

Два простых способов я знаю для этого:

  1. вручную загрузить зависимые сборки заранее с Assembly.Load.

  2. обрабатывает событие AssemblyResolve для домена, который загружает сборку с дополнительными зависимостями сборки.

Как по существу, вам необходимо знать зависимости для сборки, которую вы пытаетесь загрузить заранее, но я не думаю, что это такой большой вопрос.

Если вы идете с первой опцией, было бы также интересно разглядеть разницу между полной нагрузкой и reflection-only Load.

Если вы предпочитаете использовать 2 (что я бы рекомендовал), вы можете попробовать что-то вроде этого, которое имеет дополнительное преимущество в работе с вложенными цепочками зависимостей (например, ссылки на MyLib.dll. Ссылки LocalStorage.dll Raven.Client. DLL ссылка NewtonSoft.Json.dll) и будет дополнительно предоставить Вам информацию о том, что зависимости она не может найти:

AppDomain.CurrentDomain.AssemblyResolve += (sender,args) => { 

    // Change this to wherever the additional dependencies are located  
    var dllPath = @"C:\Program Files\Vendor\Product\lib"; 

    var assemblyPath = Path.Combine(dllPath,args.Name.Split(',').First() + ".dll"); 

    if(!File.Exists(assemblyPath)) 
     throw new ReflectionTypeLoadException(new[] {args.GetType()}, 
      new[] {new FileNotFoundException(assemblyPath) }); 

    return Assembly.LoadFrom(assemblyPath); 
}; 
+1

Удивительный! Я думаю, что ваши последние две ссылки на «путь» должны быть «assemblyPath», верно? – gf131072

+0

Да спасибо, исправлено сейчас. – nathanchere

Смежные вопросы