Предварительная загрузка сборки не работает

Я пишу тест, чтобы проверить, правильно ли зарегистрированы все контроллеры в моей конфигурации Unity. В рамках моего теста я использую отражение для проверки всех неабстрактных классов, наследуемых от System.Web.Mvc.Controller. Тем не менее, я постоянно получаю System.Reflection.ReflectionTypeLoadException. Я нахожу это странным по двум причинам:

  1. У меня есть оператор using в верхней части моего файла, который должен автоматически загружать эту конкретную сборку при запуске теста.
  2. Я также попытался предварительно загрузить сборку.

Мой код:

using System.Linq;
using System.Reflection;
using System.Text;
using System.Web.Mvc;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Unity;

namespace Presentation.Tests
{
    [TestClass]
    public class UnityTests
    {
        [TestMethod]
        public void UnityRegistration_ControllersInitialize()
        {
            // Initialize the container the same way we do in the code
            // but make sure that the container is disconnected from the application
            // so we don't accidentally change runtime behavior through testing
            var container = UnityRegistration.Initialize(new UnityContainer());

            // Get all the controllers in the presentation layer so we can check whether or not
            // they can all be constructed at runtime
            Assembly.Load("System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");
            var assembly = Assembly.ReflectionOnlyLoad("Presentation, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null");
            var ctrls = assembly.GetTypes()
                .Where(t => t.IsAssignableFrom(typeof (Controller)) && !t.IsAbstract && t.IsClass);

            var builder = new StringBuilder();
            foreach (var ctrl in ctrls)
            {
                // Check resolution on each type. If resolution fails or
                // the result is null then we should record the error
                bool isErr;
                try
                {
                    var obj = container.Resolve(ctrl);
                    isErr = obj == null;
                }
                catch
                {
                    isErr = true;
                }

                if (isErr)
                {
                    builder.AppendLine(string.Format("Controller of type {0} could not be resolved.", ctrl.Name));
                }
            }

            string errors = builder.ToString();
            if (!string.IsNullOrWhiteSpace(errors))
            {
                Assert.Fail(errors);
            }
        }
    }
}

Обратите внимание, что ссылка на Controller здесь относится конкретно к System.Web.Mvc.Controller.

Выброшенное исключение не имело внутреннего исключения и имело большое количество исключений загрузчика, все из которых указывали Cannot resolve dependency to assembly 'System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' because it has not been preloaded. When using the ReflectionOnly APIs, dependent assemblies must be pre-loaded or loaded on demand through the ReflectionOnlyAssemblyResolve event.

Может ли кто-нибудь объяснить, почему предварительная загрузка не работает таким образом, и как правильно обеспечить загрузку правильных сборок?


person Woody1193    schedule 09.10.2018    source источник
comment
Только оператор using не вызовет загрузку сборки, которую вы должны использовать, иначе она будет оптимизирована. Вы можете зарегистрировать AssemblyResolveEvent и посмотреть, какие события он пытается разрешить. docs.microsoft.com/en-us/dotnet/api/   -  person Rand Random    schedule 09.10.2018
comment
Что именно вы имеете в виду, я также пытался предварительно загрузить сборку?   -  person John Wu    schedule 09.10.2018
comment
ReflectionTypeLoadException, что такое исключения загрузчика и внутреннее исключение?   -  person JSteward    schedule 09.10.2018
comment
Кроме того, для метода Assembly.ReflectionOnlyLoad требуется FullName из Assemlby, а ваш ввод Presentation не похож на FullName - docs.microsoft.com/en-us/dotnet/api/   -  person Rand Random    schedule 09.10.2018
comment
@JohnWu Я имею в виду, что я попытался решить проблему, вызвав Assembly.Load с полным именем сборки System.Web.Mvc в качестве аргумента, который, как я понимаю, предварительно загружает ее.   -  person Woody1193    schedule 09.10.2018
comment
@JSteward Я добавил сведения об исключении   -  person Woody1193    schedule 09.10.2018
comment
@RandRandom Я не уверен, что следую. Когда я звоню Assembly.ReflectionOnlyLoad, я все еще могу получить информацию о сборке. Разве он не вернет null, если я не предоставлю достаточно информации для его загрузки?   -  person Woody1193    schedule 09.10.2018
comment
@RandRandom Кроме того, я ссылаюсь на объект Controller в сборке System.Web.Mvc. Это не считается его использованием?   -  person Woody1193    schedule 09.10.2018
comment
@RandRandom Я изменил свой код, чтобы использовать полное имя Presentation, но это никак не повлияло на исключение.   -  person Woody1193    schedule 09.10.2018
comment
Существуют и другие события домена приложения, которые вы можете просмотреть, чтобы проверить, что происходит, пока вы пытаетесь загрузить сборку/тип разрешения, которые предоставят больше информации.   -  person Mrinal Kamboj    schedule 09.10.2018
comment
Есть еще один способ: SimpleInjector предоставляет встроенный механизм проверки для проверки конфигураций DI в тестовой настройке, проверьте это, проверьте конфигурацию контейнера   -  person Mrinal Kamboj    schedule 09.10.2018


Ответы (1)


От Microsoft Документы:

Контекст загрузки только для отражения позволяет проверять сборки, скомпилированные для других платформ или других версий .NET Framework. Код, загруженный в этот контекст, можно только просмотреть; его нельзя выполнить. Это означает, что объекты не могут быть созданы, потому что конструкторы не могут быть выполнены. Поскольку код не может быть выполнен, зависимости не загружаются автоматически. Если вам нужно изучить их, вы должны загрузить их самостоятельно.

И в вашем коде:

var obj = container.Resolve(ctrl);

Вы не можете использовать тип ctrl ни для чего, кроме как для его проверки. Вы не можете создавать какие-либо объекты, которые зависят от него.

person apocalypse    schedule 09.10.2018