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