预装组装似乎不起作用

时间:2018-10-09 17:47:08

标签: c# assembly-loading

我正在编写一个测试,以检查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.

有人可以解释一下为什么预加载似乎不能以这种方式工作,以及我如何正确地确保正确的程序集被加载?

1 个答案:

答案 0 :(得分:1)

来自Microsoft Docs

  

仅反射加载上下文允许您检查程序集   为其他平台或其他版本的.NET编译   框架。加载到此上下文中的代码只能进行检查;它   无法执行。这意味着无法创建对象,因为   构造函数无法执行。由于无法执行代码,   依赖项不会自动加载。如果您需要检查   它们,您必须自己加载它们。

在您的代码中:

var obj = container.Resolve(ctrl);

除了检查之外,您不能使用ctrl类型做任何事情。您不能创建任何依赖它的对象。