mvc模拟实现

1.定义httpmodule
  <system.webServer>
    <modules>    
      <add name="UrlRoutingModule"  type="WebApp.UrlRoutingModule,WebApp"/>
    </modules>
    <validation validateIntegratedModeConfiguration="false" />
  </system.webServer>
2.对应的mvc类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Web;
using System.Web.Compilation;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace WebApp
{
    /// <summary>
    /// 二次封装的请求上下文:包括原始的HttpContextBase和经过提取的路由数据对象
    /// </summary>
    public class RequestContext
    {
        public virtual HttpContextBase HttpContext { get; set; }
        public virtual RouteData RouteData { get; set; }
    }
    public interface IRouteHandler
    {
        IHttpHandler GetHttpHandler(RequestContext requestContext);
    }
    public abstract class RouteBase
    {
        public abstract RouteData GetRouteData(HttpContextBase httpContext);
    }
    public class RouteData
    {
        public IDictionary<string, object> Values { get; private set; }
        public IDictionary<string, object> DataTokens { get; private set; }
        public IRouteHandler RouteHandler { get; set; }
        public RouteBase Route { get; set; }
        public RouteData()
        {
            this.Values = new Dictionary<string, object>();
            this.DataTokens = new Dictionary<string, object>();
            this.DataTokens.Add("namespaces", new List<string>());
        }
        public string Controller
        {
            get
            {
                object controllerName = string.Empty;
                this.Values.TryGetValue("Controller", out controllerName);
                return controllerName.ToString();
            }
        }
        public string ActionName
        {
            get
            {
                object actionName = string.Empty;
                this.Values.TryGetValue("Action", out actionName);
                return actionName.ToString();
            }
        }

    }
    public class Route : RouteBase
    {
        public IRouteHandler RouteHandler { get; set; }
        public string Url { get; set; }
        public IDictionary<string, object> DataTokens { get; set; }
        public Route()
        {
            this.DataTokens = new Dictionary<string, object>();
            this.RouteHandler = new MvcRouteHandler();
        }
        public override RouteData GetRouteData(HttpContextBase httpContext)
        {
            IDictionary<string, object> variables;
            //如 AppRelativeCurrentExecutionFilePath的值~/home/index,前两个是~/我们从第三位取值,
            //所以substring(2)的结果是home/index match返回返回符合路由规则的路由参数这里 字典里controller:"home",action:"index"
            if (this.Match(httpContext.Request.AppRelativeCurrentExecutionFilePath.Substring(2), out variables))
            {
                RouteData routeData = new RouteData();
                foreach (var item in variables)
                {
                    routeData.Values.Add(item.Key, item.Value);

                }
                foreach (var item in DataTokens)
                {
                    routeData.DataTokens.Add(item.Key, item.Value);

                }
                routeData.RouteHandler = this.RouteHandler;
                return routeData;
            }
            return null;
        }

        protected bool Match(string requestUrl, out IDictionary<string, object> variables)
        {
            variables = new Dictionary<string, object>();
            string[] strArray1 = requestUrl.Split('/');
            string[] strArray2 = this.Url.Split('/');//其中的某条路由规则
            if (strArray1.Length != strArray2.Length)
            {
                return false;
            }
            for (int i = 0; i < strArray2.Length; i++)
            {
                if (strArray2[i].StartsWith("{") && strArray2[i].EndsWith("}"))
                {
                    variables.Add(strArray2[i].Trim("{}".ToCharArray()), strArray1[i]);
                }
            }
            return true;
        }
    }

    public class RouteTable
    {
        public static RouteDictionary Routes { get; private set; }
        static RouteTable()
        {
            Routes = new RouteDictionary();
        }

    }

    public class RouteDictionary : Dictionary<string, RouteBase>
    {
        public RouteData GetRouteData(HttpContextBase httpContext)
        {
            //便利global.asax添加的路由规则
            foreach (RouteBase route in this.Values)
            {
                //比如获取得到其中的某一条路由规则 "{Controller}/{Action}" 比如我们请求地址/home/index 对应的数据层次就像routeData.Value=["Controller":"home","Action":"index"]
                //routeData.RouteHandler=MvcHandler
                RouteData routeData = route.GetRouteData(httpContext);
                if (routeData != null)
                {
                    return routeData;
                }
            }
            return null;
        }
    }
    public class UrlRoutingModule : IHttpModule
    {
        public void Dispose()
        {

        }

        public void Init(HttpApplication context)
        {
            context.PostResolveRequestCache += onPostResolveRequestCache;
        }

        public virtual void onPostResolveRequestCache(object sender, EventArgs e)
        {
            HttpContextWrapper httpContext = new HttpContextWrapper(HttpContext.Current);
            RouteData routeData = RouteTable.Routes.GetRouteData(httpContext);
            if (routeData == null)
            {
                return;
            }
            RequestContext requestContext = new RequestContext
            {

                RouteData = routeData,
                HttpContext = httpContext
            };
            IHttpHandler handler = routeData.RouteHandler.GetHttpHandler(requestContext);//这里返回MvcHandler
            httpContext.RemapHandler(handler);//UrlRoutingModule使用MvcHandler处理器处理,调用响应的processrequest方法

        }
    }
    public class MvcRouteHandler : IRouteHandler
    {
        public IHttpHandler GetHttpHandler(RequestContext requestContext)
        {
            return new MvcHandler(requestContext);
        }
    }
    public class MvcHandler : IHttpHandler
    {
        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
        public RequestContext RequestContext { get; private set; }
        public MvcHandler(RequestContext requestContext)
        {
            this.RequestContext = requestContext;
        }
        public void ProcessRequest(HttpContext context)
        {
            string controllerName = this.RequestContext.RouteData.Controller;
            IControllerFactory controllerFactory = ControllerBuilder.Current.GetControllerFactory();
            IController controller = controllerFactory.CreateController(this.RequestContext, controllerName);
            controller.Execute(this.RequestContext);
        }
    }
    public interface IController
    {
        void Execute(RequestContext requestContext);
    }
    public interface IControllerFactory
    {
        IController CreateController(RequestContext requestContext, string controllerName);
    }
    public class ControllerBuilder
    {
        private Func<IControllerFactory> factoryThunk;
        public static ControllerBuilder Current { get; private set; }
        static ControllerBuilder()
        {
            Current = new ControllerBuilder();
        }
        public IControllerFactory GetControllerFactory()
        {
            return factoryThunk();
        }
        public void SetControllerFactory(IControllerFactory controllerFactory)
        {
            factoryThunk = () => controllerFactory;
        }
    }
    public class DefaultControllerFactry : IControllerFactory
    {
        private static List<Type> controllerTypes = new List<Type>();
        /// <summary>
        /// 构造函数加载所有的控制器类的类型放在controllerTypes
        /// </summary>
        static DefaultControllerFactry()
        {
            foreach (Assembly assembly in BuildManager.GetReferencedAssemblies())
            {
                foreach (Type type in assembly.GetTypes().Where(type => typeof(IController).IsAssignableFrom(type)))
                {
                    controllerTypes.Add(type);
                }
            }
        }


        /// <summary>
        /// 通过controllerTypes集合和具体的控制器名称controllerName,反射创建对应控制器
        /// </summary>
        /// <param name="requestContext"></param>
        /// <param name="controllerName"></param>
        /// <returns></returns>
        public IController CreateController(RequestContext requestContext, string controllerName)
        {
            string typeName = controllerName + "Controller";
            Type controllerType = controllerTypes.FirstOrDefault(c => string.Compare(typeName, c.Name, true) == 0);
            if (controllerType == null)
            {
                return null;
            }
            return (IController)Activator.CreateInstance(controllerType);
        }
    }

    public class ControllerBase : IController
    {
        protected IActionInvoker ActionInvoker { get; set; }
        public ControllerBase()
        {
            this.ActionInvoker = new ControllerActionInvoker();
        }
        public void Execute(RequestContext requestContext)
        {
            ControllerContext context = new ControllerContext
            {
                RequestContext = requestContext,
                Controller = this
            };
            string actionName = requestContext.RouteData.ActionName;
            this.ActionInvoker.InvokeAction(context, actionName);
        }
    }
    public interface IActionInvoker
    {
        void InvokeAction(ControllerContext context, string actionName);
    }
    /// <summary>
    /// 控制器上下文:包含控制器和二次封装过的RequestContext请求上下文
    /// </summary>
    public class ControllerContext
    {
        /// <summary>
        /// 包含使用的控制器
        /// </summary>
        public ControllerBase Controller { get; set; }
        public RequestContext RequestContext { get; set; }
    }
    public class ControllerActionInvoker : IActionInvoker
    {
        public IModelBinder ModelBinder { get; private set; }
        public ControllerActionInvoker()
        {
            this.ModelBinder = new DefaultModelBinder();
        }
        public void InvokeAction(ControllerContext controllerContext, string actionName)
        {
            MethodInfo method = controllerContext.Controller.GetType().GetMethods()
                .First(m => string.Compare(actionName, m.Name, true) == 0);
            List<object> parameters = new List<object>();
            foreach (ParameterInfo parameter in method.GetParameters())
            {
                //把请求的参数绑定对应方法参数的模型上
                parameters.Add(this.ModelBinder.BindModel(controllerContext,
                    parameter.Name, parameter.ParameterType));
            }
            ActionResult actionResult = method.Invoke(controllerContext.Controller, parameters.ToArray()) as ActionResult;
            actionResult.ExecuteResult(controllerContext);
        }
    }
    public interface IModelBinder
    {
        object BindModel(ControllerContext controllerContext, string modelName, Type modelType);
    }
    public class DefaultModelBinder : IModelBinder
    {
        public object BindModel(ControllerContext controllerContext, string modelName, Type modelType)
        {
            if (modelType.IsValueType || typeof(string) == modelType)
            {
                object instance;
                if (GetValueTypeInstance(controllerContext, modelName, modelType, out instance))
                {
                    return instance;
                }
                return Activator.CreateInstance(modelType);
            }
            object modelInstance = Activator.CreateInstance(modelType);
            foreach (PropertyInfo property in modelType.GetProperties())
            {
                if (!property.CanWrite || (!property.PropertyType.IsValueType
                    && property.PropertyType != typeof(string)))
                {
                    continue;

                }
                object propertyValue;
                if (GetValueTypeInstance(controllerContext, property.Name, property.PropertyType, out propertyValue))
                {
                    property.SetValue(modelInstance, propertyValue, null);
                }
            }
            return modelInstance;
        }
        private bool GetValueTypeInstance(ControllerContext controllerContext, string modelName, Type modelType, out object value)
        {
            System.Collections.Specialized.NameValueCollection form = HttpContext.Current.Request.Form;
            string key;
            if (null != form)
            {
                key = form.AllKeys.FirstOrDefault(k => string.Compare(k, modelName, true) == 0);
                if (key != null)
                {
                    value = Convert.ChangeType(form[key], modelType);
                    return true;
                }

            }
            key = controllerContext.RequestContext.RouteData.Values
                .Where(item => string.Compare(item.Key, modelName, true) == 0)
                .Select(item => item.Key).FirstOrDefault();
            if (null != key)
            {
                value = Convert.ChangeType(controllerContext.RequestContext.RouteData.Values[key], modelType);
                return true;
            }
            key = controllerContext.RequestContext.RouteData.DataTokens
                .Where(item => string.Compare(item.Key, modelName, true) == 0)
                .Select(item => item.Key).FirstOrDefault();

            if (null != key)
            {
                value = Convert.ChangeType(controllerContext.RequestContext.RouteData.DataTokens[key], modelType);
                return true;
            }
            value = null;
            return false;
        }

    }
    public abstract class ActionResult
    {
        public abstract void ExecuteResult(ControllerContext context);
    }
    public class RawContentResult : ActionResult
    {
        public string RawData { get; private set; }
        public RawContentResult(string rawData)
        {
            RawData = rawData;
        }
        public override void ExecuteResult(ControllerContext context)
        {
            context.RequestContext.HttpContext.Response.Write(this.RawData);
        }
    }
    public class SimpleModel
    {
        public string Controller { get; set; }
        public string Action { get; set; }
    }
    public class HomeController : ControllerBase
    {
        public ActionResult Index(SimpleModel model)
        {
            string content = string.Format("Controller:{0}<br/>Action:{1}", model.Controller, model.Action);
            return new RawContentResult(content);
        }
    }
    public partial class WebForm1 : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }
    }
}
3.global.asax
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reflection;
using System.Web;
using System.Web.Compilation;
using System.Web.Optimization;
using System.Web.Routing;
using System.Web.Security;
using System.Web.SessionState;

namespace WebApp
{
    public class Global : HttpApplication
    {
        void Application_Start(object sender, EventArgs e)
        {
            // 在应用程序启动时运行的代码
            //RouteConfig.RegisterRoutes(RouteTable.Routes);
            //BundleConfig.RegisterBundles(BundleTable.Bundles);

            RouteTable.Routes.Add("default",
                new Route { Url = "{Controller}/{Action}" });

            ControllerBuilder.Current.SetControllerFactory(new DefaultControllerFactry());
        }
    }

}

 

转载于:https://www.cnblogs.com/kexb/p/8325574.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值