Asp.net mvc 4 MVC4和x2B中应用程序重新加载的解决方案失败;统一

Asp.net mvc 4 MVC4和x2B中应用程序重新加载的解决方案失败;统一,asp.net-mvc-4,unity-container,Asp.net Mvc 4,Unity Container,我正在开发一个ASP.NETMVC4应用程序,使用Unity3作为DI框架。 我以模块化的方式设计了架构,创建了几个卫星库项目(facade、managers、DB适配器等),所有这些项目都静态链接到应用程序(这意味着作为web项目的引用添加)。 这种体系结构背后的原因是允许在其他上下文中重用(例如,一个单独的基于REST的后端服务,作为独立的web项目实现) 我正在使用依赖注入,它发生在web项目级别,但也发生在附属DLL中。为了集中DI解析,我使用了一个简单的接口 public interf

我正在开发一个ASP.NETMVC4应用程序,使用Unity3作为DI框架。 我以模块化的方式设计了架构,创建了几个卫星库项目(facade、managers、DB适配器等),所有这些项目都静态链接到应用程序(这意味着作为web项目的引用添加)。 这种体系结构背后的原因是允许在其他上下文中重用(例如,一个单独的基于REST的后端服务,作为独立的web项目实现)

我正在使用依赖注入,它发生在web项目级别,但也发生在附属DLL中。为了集中DI解析,我使用了一个简单的接口

public interface IIocInstaller
{
    void Setup(IUnityContainer container);
}
public class AssemblyInjector
{
    /// <summary>
    /// Initialize IoC in all assemblies implementing the IocExportAssembly attribute
    /// </summary>
    /// <param name="container"></param>
    /// <param name="assemblyPrefix">The prefix of the assembly names to load</param>
    public static void RegisterAssemblyTypes(IUnityContainer container, string assemblyPrefix)
    {
        var bootstrapers = EnumerateIocBootstraperTypes(assemblyPrefix);

        foreach ( Type type in bootstrapers )
        {
            var instance = (IIocInstaller) Activator.CreateInstance(type);
            instance.Setup(container);
        }
    }

    /// <summary>
    /// Given a list of assemblies, find all types exposing the 
    /// <see cref="IocExportAssemblyAttribute"/> attribute
    /// </summary>
    /// <param name="assemblyPrefix">The prefix of the assembly names to load</param>
    /// <returns>list of types exposing the <see cref="IocExportAssemblyAttribute"/> attribute</returns>
    private static IEnumerable<Type> EnumerateIocBootstraperTypes(string assemblyPrefix)
    {
        var assemblies = EnumerateIocAssemblies(assemblyPrefix);
        var iocInterface = typeof(IIocInstaller);

        var bootstrapers = assemblies.SelectMany(s => s.GetTypes())
            .Where(iocInterface.IsAssignableFrom);

        return bootstrapers;
    }

    /// <summary>
    /// Enumerate and return all assemblies whose name starts by "Eden.SMS"
    /// </summary>
    /// <returns><see cref="IEnumerable{T}"/>list of assemblies</returns>
    /// <param name="assemblyPrefix">The prefix of the assembly names to load</param>
    private static IEnumerable<Assembly> EnumerateIocAssemblies(string assemblyPrefix)
    {
        return from assembly in AppDomain.CurrentDomain.GetAssemblies()
                     where assembly.GetName().Name.StartsWith(assemblyPrefix)
                     select assembly;
    }
}
每个库项目都有一个实现该接口的类。web应用程序使用反射扫描所有加载的程序集,查找实现接口的类,并调用Setup方法

当我启动应用程序时,一切正常。但是,当web服务器由于不活动而卸载web应用时,在下一个请求中会引发以下异常:

[InvalidOperationException: The type ICustomerFacade does not have an accessible constructor.]
   Microsoft.Practices.ObjectBuilder2.DynamicMethodConstructorStrategy.ThrowForNullExistingObject(IBuilderContext context) +178
   lambda_method(Closure , IBuilderContext ) +25
   Microsoft.Practices.ObjectBuilder2.<>c__DisplayClass1.<GetBuildMethod>b__0(IBuilderContext context) +35
   Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlan.BuildUp(IBuilderContext context) +10
   Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context) +196
   Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context) +193
   Microsoft.Practices.ObjectBuilder2.BuilderContext.NewBuildUp(NamedTypeBuildKey newBuildKey) +113
   Microsoft.Practices.Unity.ObjectBuilder.NamedTypeDependencyResolverPolicy.Resolve(IBuilderContext context) +48
   lambda_method(Closure , IBuilderContext ) +111
   Microsoft.Practices.ObjectBuilder2.<>c__DisplayClass1.<GetBuildMethod>b__0(IBuilderContext context) +35
   Microsoft.Practices.ObjectBuilder2.DynamicMethodBuildPlan.BuildUp(IBuilderContext context) +10
   Microsoft.Practices.ObjectBuilder2.BuildPlanStrategy.PreBuildUp(IBuilderContext context) +196
   Microsoft.Practices.ObjectBuilder2.StrategyChain.ExecuteBuildUp(IBuilderContext context) +193
   Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name, IEnumerable`1 resolverOverrides) +165

[ResolutionFailedException: Resolution of the dependency failed, type = "Eden.SMS.UI.Web.Controllers.CustomersController", name = "(none)".
Exception occurred while: while resolving.
Exception is: InvalidOperationException - The type ICustomerFacade does not have an accessible constructor.
-----------------------------------------------
At the time of the exception, the container was:

  Resolving Eden.SMS.UI.Web.Controllers.CustomersController,(none)
  Resolving parameter "customerFacade" of constructor Eden.SMS.UI.Web.Controllers.CustomersController(Eden.SMS.Service.Facades.Interface.ICustomerFacade customerFacade)
    Resolving Eden.SMS.Service.Facades.Interface.ICustomerFacade,(none)
]
   Microsoft.Practices.Unity.UnityContainer.DoBuildUp(Type t, Object existing, String name, IEnumerable`1 resolverOverrides) +329
   Microsoft.Practices.Unity.UnityContainer.Resolve(Type t, String name, ResolverOverride[] resolverOverrides) +15
   Microsoft.Practices.Unity.UnityContainerExtensions.Resolve(IUnityContainer container, Type t, ResolverOverride[] overrides) +18
   Unity.Mvc4.UnityDependencyResolver.GetService(Type serviceType) +67
   System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +41

[InvalidOperationException: An error occurred when trying to create a controller of type 'Eden.SMS.UI.Web.Controllers.CustomersController'. Make sure that the controller has a parameterless public constructor.]
   System.Web.Mvc.DefaultControllerActivator.Create(RequestContext requestContext, Type controllerType) +178
   System.Web.Mvc.DefaultControllerFactory.GetControllerInstance(RequestContext requestContext, Type controllerType) +77
   System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext requestContext, String controllerName) +66
   System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory) +191
   System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +50
   System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state) +48
   System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +16
   System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +301
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155
并取消对此的注释

RegisterSatelliteTypes(container);
它按预期工作(web服务器卸载应用程序后不会引发异常)。 该更改禁用了实现IIocInstaller的类的动态查找,取而代之的是对每个附属程序集的直接调用


这个解决方案修复了这个bug,但我想坚持原来的“动态”计划。所以我想弄清楚为什么会发生这种情况,以及如何解决它。有什么建议吗?

我认为您的问题在于.Net Framework将DLL加载到AppDomain的方式如何:

NET Framework延迟将程序集加载到当前 AppDomain,直到需要它们为止。例如,如果你打电话到 仅来自第三方DLL SomeMethod()的第三方库 通常在第一次运行SomeMethod()之前不会加载

AppDomain.getAssemblys()为您提供所有已安装的程序集 已加载到当前AppDomain

好消息是有一个方法
BuildManager.getReferencedAssemblys()
,它返回从Web.config和其他地方引用的所有程序集的列表,并将这些程序集加载到当前AppDomain中

这就是与您类似的问题的原因,使用
BuildManager.getReferenceAssemblys()
而不是
AppDomain.CurrentDomain.getAssemblys()
解决了这个问题


希望有帮助

谢谢,丹尼尔,我会检查一下,然后告诉你。答案很有道理:)@Antonio有帮助吗?还没有-在重新开始之前还有一个bug需要解决。我会尽快做的,但可能不会早于几天。不用担心,我只是好奇而已!仅供参考,我还没有尝试-项目暂时搁置,但很快就会恢复,我的时间被过度分配到其他地方。。。我很好奇你的暗示是否能解决我的问题,但我想毫不仓促地把它做好。
AssemblyInjector.RegisterAssemblyTypes(container, ASSEMBLY_PREFIX);
RegisterSatelliteTypes(container);