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

简介: Codeusing System;using System.Collections.Generic;using System.Linq;using System.Text;using System.

 

img_1c53668bcee393edac0d7b3b3daff1ae.gif img_405b18b4b6584ae338e0f6ecaf736533.gif
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 枚举
指定控制绑定和由反射执行的成员和类型搜索方法的标志。

 

目录
相关文章
|
网络协议
计算机网络实验(思科模拟器Cisco Packet Tracer)——查阅本机的网络配置与网络PING命令实现
计算机网络实验(思科模拟器Cisco Packet Tracer)——查阅本机的网络配置与网络PING命令实现
计算机网络实验(思科模拟器Cisco Packet Tracer)——查阅本机的网络配置与网络PING命令实现
|
存储 机器学习/深度学习 安全
干货 | Elasticsearch7.X X-Pack基础安全实操详解
背景:大家知道elasticsearch早期版本安全部分收费(7.1 & 6.8 版本之前),实际中各个公司6.x,5.x,2.x,1.x都有在用,且非少数。 群随机投票结果如下:
干货 | Elasticsearch7.X X-Pack基础安全实操详解
|
1天前
|
数据采集 人工智能 安全
|
10天前
|
云安全 监控 安全
|
2天前
|
自然语言处理 API
万相 Wan2.6 全新升级发布!人人都能当导演的时代来了
通义万相2.6全新升级,支持文生图、图生视频、文生视频,打造电影级创作体验。智能分镜、角色扮演、音画同步,让创意一键成片,大众也能轻松制作高质量短视频。
889 150
|
15天前
|
机器学习/深度学习 人工智能 自然语言处理
Z-Image:冲击体验上限的下一代图像生成模型
通义实验室推出全新文生图模型Z-Image,以6B参数实现“快、稳、轻、准”突破。Turbo版本仅需8步亚秒级生成,支持16GB显存设备,中英双语理解与文字渲染尤为出色,真实感和美学表现媲美国际顶尖模型,被誉为“最值得关注的开源生图模型之一”。
1633 8
|
6天前
|
人工智能 前端开发 文件存储
星哥带你玩飞牛NAS-12:开源笔记的进化之路,效率玩家的新选择
星哥带你玩转飞牛NAS,部署开源笔记TriliumNext!支持树状知识库、多端同步、AI摘要与代码高亮,数据自主可控,打造个人“第二大脑”。高效玩家的新选择,轻松搭建专属知识管理体系。
362 152
|
7天前
|
人工智能 自然语言处理 API
一句话生成拓扑图!AI+Draw.io 封神开源组合,工具让你的效率爆炸
一句话生成拓扑图!next-ai-draw-io 结合 AI 与 Draw.io,通过自然语言秒出架构图,支持私有部署、免费大模型接口,彻底解放生产力,绘图效率直接爆炸。
597 152
|
9天前
|
人工智能 安全 前端开发
AgentScope Java v1.0 发布,让 Java 开发者轻松构建企业级 Agentic 应用
AgentScope 重磅发布 Java 版本,拥抱企业开发主流技术栈。
553 13