前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >通俗版《把事件当作对象进行传递》看不懂老赵的文章的朋友进

通俗版《把事件当作对象进行传递》看不懂老赵的文章的朋友进

作者头像
liulun
发布2022-05-09 11:09:54
2750
发布2022-05-09 11:09:54
举报
文章被收录于专栏:liulun
代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Reflection;
namespace zhao1
{
    #region 基础
    public class Event<T>
    {
        private object m_instance;
        private MethodInfo m_addMethod;
        private MethodInfo m_removeMethod;
        public Event(Expression<Func<T>> eventExpr)
        {
            //eventExpr是LambdaExpression类型的实例,
            //他的Body属性是lambda表达式的主体,
            //这里把lambda表达式强制转换成表达式目录树的数据结构
            var memberExpr = eventExpr.Body as MemberExpression;
            //获取memberExpr包含对象的Expression 
            //如果不是null就将表达式目录树描述的lambda表达式编译为可执行代码。并返回一个委托
            //这个委托表示由 Expression<(Of <(TDelegate>)>)描述的lambda表达式
            this.m_instance = memberExpr.Expression == null ? null : Expression.Lambda<Func<object>>(memberExpr.Expression).Compile()();
            //指定控制绑定和由反射执行的成员和类型搜索方法的标志
            var bindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.InvokeMethod |
                (this.m_instance == null ? BindingFlags.Static : BindingFlags.Instance);
            //表示memberExpr的MemberInfo。
            //MemberInfo获取有关成员属性的信息并提供对成员元数据的访问。
            var member = memberExpr.Member;
            //MemberInfo.DeclaringType属性获取声明该成员的类
            //GetMethod使用指定绑定约束搜索指定方法。
            //这里还是有些不明白
            this.m_addMethod = member.DeclaringType.GetMethod("add_" + member.Name, bindingFlags);
            this.m_removeMethod = member.DeclaringType.GetMethod("remove_" + member.Name, bindingFlags);
        }
        public Event<T> AddHandler(T handler)
        {
            //Invoke使用指定的参数调用当前实例所表示的方法或构造函数。
            this.m_addMethod.Invoke(this.m_instance, new object[] { handler });
            return this;
        }
        public Event<T> RemoveHandler(T handler)
        {
            this.m_removeMethod.Invoke(this.m_instance, new object[] { handler });
            return this;
        }
        public static Event<T> operator +(Event<T> ev, T handler)
        {
            return ev.AddHandler(handler);
        }
        public static Event<T> operator -(Event<T> ev, T handler)
        {
            return ev.RemoveHandler(handler);
        }
    }
    #endregion
    #region 工厂
    /// <summary>
    /// EventFactory类的Create方法可以避免显式地提供T类型
    /// </summary>
    public static class EventFactory
    {
        public static Event<T> Create<T>(Expression<Func<T>> eventExpr)
        {
            return new Event<T>(eventExpr);
        }
    }
    #endregion
    class Program
    {
        public event EventHandler Submit;
        static void Main(string[] args)
        {
            Program p = new Program();
            var ev = EventFactory.Create(() => p.Submit);
            ev += (sender, eventArgs) => Console.WriteLine(sender);
            p.Submit("Hello World", EventArgs.Empty);
            p.Submit("xland is using vs2010",EventArgs.Empty);
            Console.ReadKey();
        }
    }
}

表达式目录树是 lambda 表达式在内存中的数据表示形式。 它使 lambda 表达式的结构变得更加透明而明确。 在与表达式目录树中的数据进行交互时,其方式就像与任何其他数据结构交互时一样。 这种将表达式处理为数据结构的功能,使 API 能够收到可按自定义方式进行检查、转换和处理的用户代码格式。

Expression 类 提供一种基类,表示表达式目录树节点的类派生自该基类。它还包含用来创建各种节点类型的 static工厂方法。这是一个 abstract 类。

Expression.Lambda 方法 创建一个表示 lambda 表达式的表达式目录树。

Expression<(Of <(TDelegate>)>) 泛型类 以表达式目录树的形式将强类型 lambda 表达式表示为数据结构。 Expression<(Of <(TDelegate>)>) 的 NodeType 为 Lambda。

Expression.Lambda<(Of <(TDelegate>)>) 泛型方法 创建一个在编译时委托类型已知的 Expression<(Of <(TDelegate>)>)。 使用 Lambda<(Of <(TDelegate>)>)(Expression, IEnumerable<(Of <(ParameterExpression>)>)) 或 Lambda<(Of <(TDelegate>)>)(Expression, array []()[]) 方法可创建 Expression<(Of <(TDelegate>)>) 对象。

Expression<(Of <(TDelegate>)>).Compile 方法 将表达式目录树描述的 lambda 表达式编译为可执行代码。 返回一个 TDelegate 类型的委托,表示由 Expression<(Of <(TDelegate>)>) 描述的 lambda 表达式。

MemberExpression 表示访问字段或属性。继承自Expression类

MemberExpression.Expression 属性 获取字段或属性包含对象的Expression

MethodInfo 发现方法的属性并提供对方法元数据的访问。

LambdaExpression 类 描述一个 lambda 表达式。LambdaExpression 类型以表达式目录树的形式表示 lambda 表达式。Expression<(Of <(TDelegate>)>) 类型派生自 LambdaExpression,它能够更加显式地捕获 lambda 表达式的类型,也可以用于表示 lambda 表达式。在运行时,表示 lambda 表达式的表达式目录树节点始终属于类型 Expression<(Of <(TDelegate>)>)。LambdaExpression 的 NodeType 属性的值为 Lambda。使用 Lambda 工厂方法可创建 LambdaExpression 对象。

LambdaExpression.Body 属性 获取 lambda 表达式的主体。

BindingFlags 枚举 指定控制绑定和由反射执行的成员和类型搜索方法的标志。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2009-09-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档