• [转].NET 4,3,2,1其实什么也没有变(格式整理)


    最近,身边的不少程序员抱怨NET的变化太快了,觉得跟不上变化,心情很沮丧,有的甚至有放弃编程这个行业的想法.

    我这篇文章的主题是[NET 4,3,2,1其实什么也没有变],贯穿本文的例子是如何动态调用方法.本文的目的不是驳斥NET升级的无意义,只是想从一个小的技术点说明变与不变是相对的.当一个新技术出现后,了解它出现的意义,了解它的前身,了解它的后续,比盲目的追从要有用的多.

    下面看例子,(注:下面的一组例子只演示了从NET1.0 到NET4.0 中动态调用方法的常用方式,在这里我们不谈性能)

    NET4.0 中用dynamic实现动态调用方法

    在NET4.0 中可以用dynamic 定义一个对象,然后像在VB6(注不是VB.NET,是VB6.0,VB5.0,VB4.0)中那样访问对象成员.

    dynamic 定义的对象,打点没有提示,不管方法名与参数是否错误,编译时都不会报错,只有在运行时找不到方法或参数错误才会报错

    很多看了NET4.0中 dynamic人会说NET怎么这么没出息,开始学VB6.0了, 而真正了解VB的确人不会这么说.VB的普及是因为简单,而VB的终结不是因为简单,而是因为功能上的欠缺.

    NET在尽量实现汇编,C++强大功能的同时,从尽量使其像VB那样简单.

    这就是变改不变是相对,保留汇编,C++的功能与VB的简单,抛弃汇编,C++的繁琐与VB的缺陷.变的是方式,不变的是思想

    class Program

    {

      static void Main(string[] args)

      {

        object obj = new myClass();

        dynamic m =obj;

        m.test1(10, 20); //打点没有提示,运行时找不到方法会报错

        System.Console.Read();

      }

    }

    class myClass

    {

      public void test1(int x, int y)

      {

        int v = x + y;

        System.Console.WriteLine(v);

      }

    }

    NET 3.X 中用System.Linq.Expressions.Expression实现动态调用方法

    下面的例子是我在NET3.X中常用的一种动态调用用方法的方式

    我实现了一个myTool类,用myTool的execute方法可以动态调用其它类的方法, Linq有两部份内容,一个是集合运算,那是高是数学的内容,另一部分就是Expression

    //要被动态执行的类

    public class myClass

    {

      public string myMethod1(string s, int i, object o)

      {

        return s + i.ToString();

      }

      public static string myMethod2(string s, int i, object o)

      {

        return i.ToString() + s;

      }

      public void myMethod3(string s, int i, object o)

      {

        Console.WriteLine(s + i.ToString());

      }

    }

    //工具类

    sing System.Linq.Expressions;

    using System.Reflection;

    public static class myTool

    {

      public static R execute<R, T>(T executeObject, string methodName, object[] parameters)

      {

        System.Reflection.MethodInfo method = executeObject.GetType().GetMethod(methodName);

        Func<object, object[], object> executeDelegate;

        executeDelegate = getDelegate(method);

        var ro =executeDelegate(executeObject, parameters);

        return (R)(ro);

      }

      private static Func<object, object[], object> getDelegate(MethodInfo methodInfo)

      {

        ParameterExpression instanceParameter = Expression.Parameter(typeof(object), "instance");

        ParameterExpression parametersParameter = Expression.Parameter(typeof(object[]), "parameters");

        List<Expression> parameterExpressions = new List<Expression>();

        ParameterInfo[] paramInfos = methodInfo.GetParameters();

        //-参数

        for (int i = 0; i < paramInfos.Length; i++)

        {

          BinaryExpression be = Expression.ArrayIndex(parametersParameter, Expression.Constant(i));

          UnaryExpression ue = Expression.Convert(be, paramInfos[i].ParameterType);

          parameterExpressions.Add(ue);

        }

        //-判断是否为静态方法

        Expression instanceCast;

        if (methodInfo.IsStatic == true)

        {

          instanceCast = null;

        }

        else

        {

          instanceCast = Expression.Convert(instanceParameter, methodInfo.ReflectedType);

        }

        MethodCallExpression methodCall = Expression.Call(instanceCast, methodInfo, parameterExpressions);  

        //-判断是否为有返回值方法

        if (methodCall.Type == typeof(void))

        {

          Expression<Action<object, object[]>> lambda = Expression.Lambda<Action<object, object[]>>(methodCall, instanceParameter, parametersParameter);

          Action<object, object[]> execute = lambda.Compile();

          return (instance, parameters) => { execute(instance, parameters); return null; };

        }

        else

        {

          UnaryExpression castMethodCall = Expression.Convert(methodCall, typeof(object));

          Expression<Func<object, object[], object>> lambda = Expression.Lambda<Func<object, object[], object>>(castMethodCall, instanceParameter, parametersParameter);

          return lambda.Compile();

        }

      }

    }

    //调用

    class Program

    {

      static void Main(string[] args)

      {

        myClass obj = new myClass();

        string ro1 = myTool.execute<string, myClass>(obj, "myMethod1", new object[] { "wxwinter", 123, null });

        Console.WriteLine(ro1.ToString());

        string ro2 = myTool.execute<string, myClass>(obj, "myMethod2", new object[] { "wxd", 123, null });

        Console.WriteLine(ro2.ToString());

        myTool.execute<string, myClass>(obj, "myMethod3", new object[] { "lzm", 123, null });

        Console.Read();

      }

    }

    NET 2.0 中用泛型实现动态调用方法

    下面的例子是我在NET2.0中常用的一种动态调用用方法的方式

    我实现了一个myTool类,用myTool的execute方法可以动态调用其它类的方法, 

    泛型,是NET 2.0 中很重要的内容,如果你看这个例子的代码感到吃力,我的建议是先将泛型理解透了现考虑学NET3.X,NET4.0 的内容

    (补充一句,这种方式的执行性能比上例低)

    //要被动态执行的类

    public class myClass

    {

      public string myMethod1(string s, int i, object o)

      {

        return s + i.ToString();

      }

      public static string myMethod2(string s, int i, object o)

      {

        return i.ToString() + s;   

      }

      public void myMethod3(string s, int i, object o)

      {

        Console.WriteLine(s + i.ToString());

      }

    }

    //工具类

    public static class myTool

    {

      public static R execute<R, T>(T executeObject, string methodName, object[] parameters)

      {

        System.Reflection.MethodInfo method = executeObject.GetType().GetMethod(methodName);

        object ro = method.Invoke(executeObject, parameters);

        R r = (R)(ro);

        return r;

      }

    }

    //调用

    class Program

    {

      static void Main(string[] args)

      {

        myClass obj = new myClass();

        string ro1 = myTool.execute<string,myClass>(obj, "myMethod1", new object[] { "wxwinter", 123, null }); 

        Console.WriteLine(ro1.ToString());

        string ro2 = myTool.execute<string, myClass>(obj, "myMethod2", new object[] { "wxd", 123, null });

        Console.WriteLine(ro2.ToString());

        myTool.execute<string, myClass>(obj, "myMethod3", new object[] { "lzm", 123, null });

        Console.Read();

      }

    }

    NET 1.X中用返射实现动态调用方法

    下面的例子是我在NET1.1中常用的一种动态调用用方法的方式

    我实现了一个myTool类,用myTool的execute方法可以动态调用其它类的方法, 没什么好说的,这是基础

    //要被动态执行的类

    public class myClass

    {

      public string myMethod1(string s, int i, object o)

      {

        return s + i.ToString();

      }

      public static string myMethod2(string s, int i, object o)

      {

        return i.ToString() + s;

      }

      public void myMethod3(string s, int i, object o)

      {

        Console.WriteLine(s + i.ToString());

      }

    }

    //工具类

    public static class myTool

    {

      public static object execute(object executeObject, string methodName, object[] parameters)

      {

        System.Reflection.MethodInfo method = executeObject.GetType().GetMethod(methodName);

        object ro = method.Invoke(executeObject, parameters);

        return ro;

      }

    }

    //调用

    class Program

    {

      static void Main(string[] args)

      {

         object obj = new myClass();

         object ro1 = myTool.execute(obj, "myMethod1", new object[] { "wxwinter", 123, null });

         Console.WriteLine(ro1.ToString());

         object ro2 = myTool.execute(obj, "myMethod2", new object[] { "wxd", 123, null });

         Console.WriteLine(ro2.ToString());

         myTool.execute(obj, "myMethod3", new object[] { "lzm", 123, null });

         Console.Read();

      }

    }

    总结

    变与不变是相对,会Socket的学习TCP很容易,会TCP的学习HTTP很容易,会HTTP的学习WebService很容易,会WebService的学习WCF很容易

    Dos下的很多写屏技巧在WPF中还在使用.

    VB6.0中用ActivitX 创建的动态网页与现在的Silverlight也有很多相似之处

    SQL Server 2005中可以写NET代码,让我想起了FoxBase

    NET不变的是在提供更多功能的同时让其使用更简单,而NET变的只是实现这一目标的方式

  • 相关阅读:
    luogu P3657 (NOIP2017) 跳房子(二分+DP+单调队列)
    BZOJ 3331 (Tarjan缩点+树上差分)
    Libre OJ 2255 (线段树优化建图+Tarjan缩点+DP)
    LibreOJ 6177 题解(状压DP)
    BZOJ 1179 (Tarjan缩点+DP)
    BZOJ 4919 (树上LIS+启发式合并)
    BZOJ 1100 &&luogu 3454(计算几何+KMP)
    HDU 3228 题解(最小生成树)(Kruskal)(内有详细注释)
    Codeforces 1058C(思维+最大公因数)
    周记 2015.05.30
  • 原文地址:https://www.cnblogs.com/killkill/p/1372242.html
Copyright © 2020-2023  润新知