C# 统一4号(国际奥委会)和#x2B;MVC 5无法在启动期间解析类型

C# 统一4号(国际奥委会)和#x2B;MVC 5无法在启动期间解析类型,c#,asp.net-mvc,unity-container,C#,Asp.net Mvc,Unity Container,我正在使用Unity4(通过NuGet)和ASP.NETMVC5。我已经修改了所有的控制器和业务类,通过它们的构造函数将它们的依赖项作为接口接收 boostrapper类包含以下代码: public class Bootstrapper { public static IUnityContainer UnityContainer { get; set; } public static void Initialize() { InitializeUnity

我正在使用Unity4(通过NuGet)和ASP.NETMVC5。我已经修改了所有的控制器和业务类,通过它们的构造函数将它们的依赖项作为接口接收

boostrapper类包含以下代码:

public class Bootstrapper
{
    public static IUnityContainer UnityContainer { get; set; }

    public static void Initialize()
    {
        InitializeUnity();
        RegisterTypes();
    }

    private static void InitializeUnity()
    {
        UnityContainer = UnityConfig.GetConfiguredContainer();
        DependencyResolver.SetResolver(new UnityDependencyResolver(UnityContainer));
    }

    private static void RegisterTypes()
    {
        new Core.Bootstrapper().RegisterTypes(UnityContainer);
    }
}
Core.Bootstrapper().RegisterTypes的内容如下:

public IUnityContainer RegisterTypes(IUnityContainer container)
{
    // Register repositories
    container.RegisterType<IRepository, Repository>()
             .RegisterType<IBdeRepository, BdeRepository>()
             .RegisterType<IDocumentRepository, DocumentRepository>()
             .RegisterType<IHampRepository, HampRepository>()
             .RegisterType<IReportsRepository, ReportsRepository>()
             .RegisterType<ITransactionRepository, TransactionRepository>();

    // Register commands
    container.RegisterType<IBaseCommand, BaseCommand>()
             .RegisterType<IDailyLetterInfoUpdate, DailyLetterInfoUpdate>()
             .RegisterType<IDailyReconciliation, DailyReconciliation>()
             .RegisterType<InsertNewRows, InsertNewRows>()
             .RegisterType<IOrderDailyLM023, OrderDailyLM023>()
             .RegisterType<IOrderMonthlyLM012, OrderMonthlyLM012>()
             .RegisterType<IOrderMonthlyLM014, OrderMonthlyLM014>()
             .RegisterType<IPerformMonthlyRecastStatusUpdate, PerformMonthlyRecastStatusUpdate>()
             .RegisterType<IUpdateReissuedRecasts, UpdateReissuedRecasts>();

    // Register utility types
    container.RegisterType<ICsvExporter, CsvExporter>()
             .RegisterType<ILogger, Logger>();

    return container;
}
using System;
using System.Collections.Generic;
using System.Web.Mvc;

using Microsoft.Practices.Unity;

/// <summary>
/// Resolves dependencies against the current DI container.
/// </summary>
public class UnityDependencyResolver : IDependencyResolver
{
    /// <summary>
    /// The container
    /// </summary>
    private readonly IUnityContainer container;

    /// <summary>
    /// Initializes a new instance of the <see cref="UnityDependencyResolver"/> class.
    /// </summary>
    /// <param name="container">The container.</param>
    public UnityDependencyResolver(IUnityContainer container) 
    {
        this.container = container;
    }

    /// <summary>
    /// Resolves an instance of the default requested type from the container.
    /// </summary>
    /// <param name="serviceType">The <see cref="Type"/> of the object to get from the container.</param>
    /// <returns>The requested object, if it can be resolved; otherwise, <c>null</c>.</returns>
    public object GetService(Type serviceType)
    {
        return this.container.IsRegistered(serviceType) 
            ? this.container.Resolve(serviceType) 
            : null;
    }

    /// <summary>
    /// Resolves multiply registered services.
    /// </summary>
    /// <param name="serviceType">The type of the requested services.</param>
    /// <returns>The requested services.</returns>
    public IEnumerable<object> GetServices(Type serviceType)
    {
        return this.container.ResolveAll(serviceType);
    }
}

我找到了我的特殊场景的解决方案,这有点令人惊讶

我必须滚动我自己的DependencyResolver类,并使用它代替Unity提供的MVC解析器。我编写的解析器如下所示:

public IUnityContainer RegisterTypes(IUnityContainer container)
{
    // Register repositories
    container.RegisterType<IRepository, Repository>()
             .RegisterType<IBdeRepository, BdeRepository>()
             .RegisterType<IDocumentRepository, DocumentRepository>()
             .RegisterType<IHampRepository, HampRepository>()
             .RegisterType<IReportsRepository, ReportsRepository>()
             .RegisterType<ITransactionRepository, TransactionRepository>();

    // Register commands
    container.RegisterType<IBaseCommand, BaseCommand>()
             .RegisterType<IDailyLetterInfoUpdate, DailyLetterInfoUpdate>()
             .RegisterType<IDailyReconciliation, DailyReconciliation>()
             .RegisterType<InsertNewRows, InsertNewRows>()
             .RegisterType<IOrderDailyLM023, OrderDailyLM023>()
             .RegisterType<IOrderMonthlyLM012, OrderMonthlyLM012>()
             .RegisterType<IOrderMonthlyLM014, OrderMonthlyLM014>()
             .RegisterType<IPerformMonthlyRecastStatusUpdate, PerformMonthlyRecastStatusUpdate>()
             .RegisterType<IUpdateReissuedRecasts, UpdateReissuedRecasts>();

    // Register utility types
    container.RegisterType<ICsvExporter, CsvExporter>()
             .RegisterType<ILogger, Logger>();

    return container;
}
using System;
using System.Collections.Generic;
using System.Web.Mvc;

using Microsoft.Practices.Unity;

/// <summary>
/// Resolves dependencies against the current DI container.
/// </summary>
public class UnityDependencyResolver : IDependencyResolver
{
    /// <summary>
    /// The container
    /// </summary>
    private readonly IUnityContainer container;

    /// <summary>
    /// Initializes a new instance of the <see cref="UnityDependencyResolver"/> class.
    /// </summary>
    /// <param name="container">The container.</param>
    public UnityDependencyResolver(IUnityContainer container) 
    {
        this.container = container;
    }

    /// <summary>
    /// Resolves an instance of the default requested type from the container.
    /// </summary>
    /// <param name="serviceType">The <see cref="Type"/> of the object to get from the container.</param>
    /// <returns>The requested object, if it can be resolved; otherwise, <c>null</c>.</returns>
    public object GetService(Type serviceType)
    {
        return this.container.IsRegistered(serviceType) 
            ? this.container.Resolve(serviceType) 
            : null;
    }

    /// <summary>
    /// Resolves multiply registered services.
    /// </summary>
    /// <param name="serviceType">The type of the requested services.</param>
    /// <returns>The requested services.</returns>
    public IEnumerable<object> GetServices(Type serviceType)
    {
        return this.container.ResolveAll(serviceType);
    }
}
它使用本地实现而不是默认的Unity实现


奇怪的是,我正在绘制的示例应用程序在我的机器上本地运行,并且没有使用自定义解析器。没有这门课,它很好用。我不知道为什么会这样,这很麻烦(我更喜欢问题的确定性答案),但在这一点上,我很高兴我能重新开始工作。

这里有一个稍微不同的实现,对MVC部分进行了特定的排除,改编自

在启动时,这似乎是一个轻微的性能优势,但最主要的是,您不会遇到10个异常

/// <summary>
/// Resolves dependencies against the current DI container.
/// </summary>
public class UnityDependencyResolver : IDependencyResolver
{
    private readonly IUnityContainer container;
    // NB Not likely to be be big but will be frequent so use HashSet as O(1) lookup cost - see https://stackoverflow.com/questions/18651940/performance-benchmarking-of-contains-exists-and-any
    private readonly HashSet<Type> excludedTypes;

    /// <summary>
    /// Initializes a new instance of the <see cref="UnityDependencyResolver"/> class.
    /// </summary>
    /// <param name="container">The container.</param>
    public UnityDependencyResolver(IUnityContainer container)
    {
        this.container = container;
        excludedTypes = new HashSet<Type>();

        StandardExclusions();
    }

    /// <summary>
    /// Resolves an instance of the default requested type from the container.
    /// </summary>
    /// <param name="serviceType">The <see cref="Type"/> of the object to get from the container.</param>
    /// <returns>The requested object.</returns>
    public object GetService(Type serviceType)
    {
        if (typeof(IController).IsAssignableFrom(serviceType))
        {
            return container.Resolve(serviceType);
        }

        try
        {
            return excludedTypes.Contains(serviceType) ? null : container.Resolve(serviceType);
        }
        catch (ResolutionFailedException)
        {
            return null;
        }
    }

    /// <summary>
    /// Resolves multiply registered services.
    /// </summary>
    /// <param name="serviceType">The type of the requested services.</param>
    /// <returns>The requested services.</returns>
    public IEnumerable<object> GetServices(Type serviceType)
    {
        return container.ResolveAll(serviceType);
    }

    public void Exclude<T>()
    {
        Exclude(typeof(T));
    }

    public void Exclude(Type type)
    {
        excludedTypes.Add(type);
    }

    public void Include<T>()
    {
        Include(typeof(T));
    }

    public void Include(Type type)
    {
        excludedTypes.Remove(type);
    }

    private void StandardExclusions()
    {
        Exclude<System.Web.Mvc.IControllerFactory>();
        Exclude<System.Web.Mvc.IControllerActivator>();
        Exclude<System.Web.Mvc.ITempDataProviderFactory>();
        Exclude<System.Web.Mvc.ITempDataProvider>();
        Exclude<System.Web.Mvc.Async.IAsyncActionInvokerFactory>();
        Exclude<System.Web.Mvc.IActionInvokerFactory>();
        Exclude<System.Web.Mvc.Async.IAsyncActionInvoker>();
        Exclude<System.Web.Mvc.IActionInvoker>();
        Exclude<System.Web.Mvc.IViewPageActivator>();
        Exclude<System.Web.Mvc.ModelMetadataProvider>();
    }
}
//
///根据当前DI容器解析依赖项。
/// 
公共类UnityDependencyResolver:IDependencyResolver
{
专用只读IUnityContainer容器;
//NB不太可能很大,但会很频繁,所以使用哈希集作为O(1)查找成本-请参阅https://stackoverflow.com/questions/18651940/performance-benchmarking-of-contains-exists-and-any
私有只读哈希集排除类型;
/// 
///初始化类的新实例。
/// 
///集装箱。
公共单元依赖解析程序(IUnityContainer容器)
{
this.container=容器;
excludedTypes=新HashSet();
标准除外责任();
}
/// 
///从容器解析默认请求类型的实例。
/// 
///要从容器中获取的对象的名称。
///请求的对象。
公共对象GetService(类型serviceType)
{
if(typeof(IController).IsAssignableFrom(serviceType))
{
返回容器解析(serviceType);
}
尝试
{
return excludedTypes.Contains(serviceType)?null:container.Resolve(serviceType);
}
捕获(解决失败异常)
{
返回null;
}
}
/// 
///解析多个注册服务。
/// 
///请求的服务的类型。
///请求的服务。
公共IEnumerable GetServices(类型serviceType)
{
返回容器.ResolveAll(serviceType);
}
公共无效排除()
{
排除(类型(T));
}
公共无效排除(类型)
{
排除类型。添加(类型);
}
公开无效包括()
{
包括(类型(T));
}
公共void包括(类型)
{
排除类型。删除(类型);
}
私人保险除外责任()
{
排除();
排除();
排除();
排除();
排除();
排除();
排除();
排除();
排除();
排除();
}
}
如果确实重写了一个标准MVC接口,则可以使用

var resolver = new UnityDependencyResolver(container);
resolver.Include<System.Web.Mvc.IActionInvoker>();
var解析器=新的unitydependencysolver(容器);
解析程序Include();

您是否成功执行过注册表类型()?是。有关引发异常的位置的详细信息,请参阅更新。是否尝试手动注册
ITempDataProviderFactory
?似乎缺少默认实现。可能是一些错误或版本不匹配。这是一篇有趣的文章,如果你找到了答案,请发布答案。@kat1330找到了答案。见答案部分。迈克。您的方法唯一的缺点是Unity在IsRegistered上不是很有效,因此在大型容器上,它可能比异常抛出花费更多的时间