C# 高阶函数的应用~~~~用委托代替new来传递

以.NET Web程序注册全局路由为例,先看以下的代码

1、路由Route类,包含一个IHttpHandler,一个处理请求程序的属性,在构造函数中需要去传递一个IHttpHandler的一个对象

public class Route
{
        public Route(string url, object defaults, IHttpHandler handler)
        {
            this.Url = url;
            this.RouteHandler = handler;
            Defaults = new Dictionary<string, object>();
            var defaultsProps = defaults.GetType().GetProperties();
            foreach (var item in defaultsProps)
            {
                Defaults.Add(item.Name, item.GetValue(defaults));
            }
        }

        public string Url { get; set; }

        /// <summary>
        /// 当前请求处理程序
        /// </summary>
        public IHttpHandler RouteHandler { get; set; }

        public IDictionary<string, object> Defaults { get; set; }
}

2、程序全局入口,注册全局的路由表

protected void Application_Start(object sender, EventArgs e)
{
        RouteTable.Routes.MapRoute(
                "{controller}/{action}",
                new { Controller = "Product", Action = "Execute" });
}

3、通过一个扩展方法MapRoute去注册全局路由表,在这个扩展方法中去注册IHttpHandler时,new一个MvcHandler(继承IHttpHandler的具体对象)作为参数传递过去

public static class RouteExtend
{
        public static void MapRoute(this IList<Route> source, string url, object defaults)
        {
            MapRoute(source, url, default, new MvcHandler());
        }

        public static void MapRoute(this IList<Route> source, string url, object defaults, IHttpHandler handler)
        {
            source.Add(new Route(
                url,
                defaults,
                handler));
        }
}

4、当解析完路由,分配好处理的路由对象时可以通过route.RouteHandler()来得到对象,并执行其他的一系列操作。

route.RouteHandler()

当这样去coding代码的时候,会存在几个问题:

①:在构造路由时,会直接去new一个对象,而且不管这个对象是否要被调用,都会去new

②:当地址访问时,会造成对象的共享问题,一直存在静态路由集合RouteTable.Routes属性中,会造成无法释放,占用内存的情况

所以,可以修改程序,利用委托的方式来进行代码的优化

1、首先我们来修改Route类,将原来的静态属性RouteHandler,改为委托的Func<IHttpHandler>的形式

public class Route
{
        public Route(string url, object defaults, Func<IHttpHandler> getHandler)
        {
            this.Url = url;
            this.GetRouteHandler = getHandler;
            Defaults = new Dictionary<string, object>();
            var defaultsProps = defaults.GetType().GetProperties();
            foreach (var item in defaultsProps)
            {
                Defaults.Add(item.Name, item.GetValue(defaults));
            }
        }

        public string Url { get; set; }

        /// <summary>
        /// 当前请求处理程序
        /// </summary>
        public Func<IHttpHandler> GetRouteHandler { get; set; }

        public IDictionary<string, object> Defaults { get; set; }
}

2、在通过扩展方法注册全局路由表的时候,传递一个匿名的委托,委托里面来进行new操作

public static class RouteExtend
{
        public static void MapRoute(this IList<Route> source, string url, object defaults)
        {
            MapRoute(source, url, default, () => { return new MvcHandler(); });
        }

        public static void MapRoute(this IList<Route> source, string url, object defaults, Func<IHttpHandler> getHandler)
        {
            source.Add(new Route(
                url,
                defaults,
                getHandler));
        }
}

3、这样在外部调用的时候,就可以通过执行委托的形式来获得对象,然后在进行其他的操作

  var handler = route.GetRouteHandler();

这样做的好处:

①:当我们在构造的时候,并不传入具体的对象,而是传入一个允许创建对象的操作,只有当我们真正调用的时候,才会去创建对象

②:相比于之前的静态属性而言,静态属性是会被存储在内存中的,而通过委托,创建出来方法的返回值,是不会存储的,这样对内存而言是一种优化。

猜你喜欢

转载自blog.csdn.net/KoHsin_/article/details/107361776