• 探索RegisterAllAreas


    在MVC中注册Area时,我们一般会在相应的区域下定义一个继承与AreaRegistration的类,代码如下:

    public class AdminAreaRegistration : AreaRegistration
    {
        public override string AreaName
        {
            get
            {
                return "Admin";
            }
        }
    
        public override void RegisterArea(AreaRegistrationContext context)
        {
            context.MapRoute(
                "Admin_default",
                "Admin/{controller}/{action}/{id}",
                new { action = "Index", id = UrlParameter.Optional }
            );
        }
    }

    那么问题来了,类AdminAreaRegistration是在什么时候被实例化的,方法RegisterArea是何时被调用的?

    1、Global中注册所有区域

    AreaRegistration.RegisterAllAreas();

    2、查看AreaRegistration.RegisterAllAreas源码

    internal static void RegisterAllAreas(RouteCollection routes, IBuildManager buildManager, object state)
    {
        //从缓存以及组件中查找所有的AreaRegistration
        List<Type> filteredTypesFromAssemblies = TypeCacheUtil.GetFilteredTypesFromAssemblies("MVC-AreaRegistrationTypeCache.xml", new Predicate<Type>(AreaRegistration.IsAreaRegistrationType), buildManager);
        foreach (Type current in filteredTypesFromAssemblies)
        {
            AreaRegistration areaRegistration = (AreaRegistration)Activator.CreateInstance(current);
    
            areaRegistration.CreateContextAndRegister(routes, state);
        }
    }

    3、从缓存及引用程序集中查找Type

    public static List<Type> GetFilteredTypesFromAssemblies(string cacheName, Predicate<Type> predicate, IBuildManager buildManager)
    {
        TypeCacheSerializer serializer = new TypeCacheSerializer();
        //从缓存中查找AreaRegistration
        List<Type> list = TypeCacheUtil.ReadTypesFromCache(cacheName, predicate, buildManager, serializer);
        if (list != null)
        {
            return list;
        }
        //从组件中查找AreaRegistration
        list = TypeCacheUtil.FilterTypesInAssemblies(buildManager, predicate).ToList<Type>();
        //添加缓存
        TypeCacheUtil.SaveTypesToCache(cacheName, list, buildManager, serializer);
        return list;
    }

    4、从程序集中查找Type

    private static IEnumerable<Type> FilterTypesInAssemblies(IBuildManager buildManager, Predicate<Type> predicate)
    {
        IEnumerable<Type> enumerable = Type.EmptyTypes;
        //获取所有被引用的组件
        ICollection referencedAssemblies = buildManager.GetReferencedAssemblies();
        foreach (Assembly assembly in referencedAssemblies)
        {
            Type[] types;
            try
            {
                //获取组件中的所有类型
                types = assembly.GetTypes();
            }
            catch (ReflectionTypeLoadException ex)
            {
                types = ex.Types;
            }
    
            enumerable = enumerable.Concat(types);
        }
    
        //返回所有类型中的AreaRegistration
        return from type in enumerable
        where TypeCacheUtil.TypeIsPublicClass(type) && predicate(type)
        select type;
    }

    5、此处使用predicate(type),不得不回到步骤2看看传入的是啥

    private static bool IsAreaRegistrationType(Type type)
    {
        return typeof(AreaRegistration).IsAssignableFrom(type) && type.GetConstructor(Type.EmptyTypes) != null;
    }

    6、此时已找到所有的AreaRegistration类,再次回到步骤2,创建AreaRegistration实例,并调用方法RegisterArea

    internal void CreateContextAndRegister(RouteCollection routes, object state)
    {
        AreaRegistrationContext areaRegistrationContext = new AreaRegistrationContext(this.AreaName, routes, state);
        string @namespace = base.GetType().Namespace;
        if (@namespace != null)
        {
            areaRegistrationContext.Namespaces.Add(@namespace + ".*");
        }
        this.RegisterArea(areaRegistrationContext);
    }

    由以上代码可以看书,方法RegisterAllAreas就是简单粗暴的将所有引用程序集中的类型遍历一遍,找到所有的AreaRegistration,并调用注册区域方法。

    为了验证以上观点,特做了以下测试。

        新建一个类库程序,并在类库程序中注册区域,观察是否注册成功。文件结构如下

    测试结果:

    由于本人也是最近才接触MVC,在学习过程中碰到一些问题,特此备注

    1、Mvc定义区域外层文件夹约定为Areas
    2、Views文件夹下一定要有web.config,否则会报错(当前上下文中不存在名称“ViewBag”),可以复制项目Views下自动生成的Web.config
    3、注册区域可以在其他被引用的项目中(AreaRegistration)

  • 相关阅读:
    阿里云ECS安全组之新手不得不面对的问题
    【云栖风向标】VOL.3:阿里云:对不起_这个官司我不服!
    Linux全自动安装wdcp面板脚本
    “程序员”和“码农”究竟有什么区别?
    安卓新标准出台_告别乱弹窗_你的手机真会省电么?
    16年程序员平均工资122478元_你拖后腿了没?
    6.5世界环境日!来聊聊那些你想不到的环保黑科技?
    小扎曝Facebook北极数据中心图片_最先进数据中心都建在哪?
    js之单例模式
    js 之 call 、 apply
  • 原文地址:https://www.cnblogs.com/kai364/p/5638866.html
Copyright © 2020-2023  润新知