C# Dynamic之:ExpandoObject,DynamicObject,DynamicMetaOb的应用(上)

那我开始讲解C# Dynamic之:ExpandoObject,DynamicObject,DynamicMetaObject的应用(上)的完整攻略。

1. 概述

首先,需要了解什么是动态类型,以及为什么需要使用动态类型。在C#中,变量的类型实际上是由编译器推断出来的,也就是静态类型。而动态类型是指在运行时才确定类型的类型。动态类型的主要作用是在不确定类型时,可以通过运行时信息来确定类型,从而实现更灵活的编程。

在C#中,提供了一些机制来支持动态类型,其中ExpandoObject、DynamicObject和DynamicMetaObject是比较常见的。

2. ExpandoObject

ExpandoObject是一种可以动态添加属性和方法的对象。通过ExpandoObject,可以在运行时动态添加属性和方法,而不需要在编译时就确定属性和方法。下面是一个使用ExpandoObject的示例:

dynamic person = new ExpandoObject();
person.Name = "John";
person.Age = 30;
person.SayHello = (Action)(() => Console.WriteLine("Hello, my name is " + person.Name));
person.SayHello();

在上面的示例中,我们创建了一个ExpandoObject对象,并且动态的添加了Name、Age属性和SayHello方法。通过这种方式,我们可以灵活的定义对象的属性和方法,并在运行时动态的添加和使用它们。

3. DynamicObject

DynamicObject是一个可以重写成员访问的类。通过继承DynamicObject,可以动态定义对象的成员访问行为。下面是一个使用DynamicObject的示例:

class MyDynamicClass : DynamicObject
{
    private readonly Dictionary<string, object> _dictionary = 
        new Dictionary<string, object>();

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        string name = binder.Name.ToLower();
        return _dictionary.TryGetValue(name, out result);
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        _dictionary[binder.Name.ToLower()] = value;
        return true;
    }
}

dynamic obj = new MyDynamicClass();
obj.Name = "John";
Console.WriteLine(obj.Name);

在上面的示例中,我们自定义了一个MyDynamicClass类,该类继承自DynamicObject并重载了TryGetMember和TrySetMember方法。在TryGetMember和TrySetMember方法中,我们实现了访问对象成员的方式,例如可以将对象的属性名称转化为小写后在Dictionary中查找对应的值。

4. DynamicMetaObject

DynamicMetaObject是一个提供动态行为元数据的类。通过重载DynamicMetaObject,可以实现更高级的动态类型行为。下面是一个使用DynamicMetaObject的示例:

class MyDynamicClass : DynamicObject
{
    private readonly Dictionary<string, object> _dictionary =
        new Dictionary<string, object>();

    public override DynamicMetaObject GetMetaObject(Expression parameter)
    {
        return new MyDynamicMetaObject(parameter, this);
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        string name = binder.Name.ToLower();
        return _dictionary.TryGetValue(name, out result);
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        _dictionary[binder.Name.ToLower()] = value;
        return true;
    }
}

class MyDynamicMetaObject : DynamicMetaObject
{
    public MyDynamicMetaObject(Expression expression, object value)
        : base(expression, BindingRestrictions.Empty, value)
    {
    }

    public override DynamicMetaObject BindGetMember(GetMemberBinder binder)
    {
        var name = Expression.Constant(binder.Name.ToLower());
        var dictionary = Expression.Property(Expression.Constant(Value), "Dictionary");
        var index = Expression.Call(dictionary, "TryGetValue", null, name,
            Expression.Variable(typeof(object)));
        var restriction = BindingRestrictions.GetTypeRestriction(Expression, LimitType);
        var value = Expression.Variable(typeof(object));

        var fallback = Expression.Block(
            Expression.Assign(value, Expression.Default(typeof(object))),
            Expression.Convert(value, binder.ReturnType));

        var binding = new DynamicMetaObject(
            Expression.Block(
                new[] { value },
                Expression.Condition(index, Expression.Convert(Expression.Property(
                                                Expression.Variable(value),
                                                "Value"),
                                                binder.ReturnType),
                                      fallback)),
            restriction,
            this);

        return binding;
    }
}

dynamic obj = new MyDynamicClass();
obj.Name = "John";
Console.WriteLine(obj.Name);

在上面的示例中,我们自定义了一个MyDynamicClass类,该类继承自DynamicObject并重载了GetMetaObject、TryGetMember和TrySetMember方法。在GetMetaObject方法中,我们返回了一个MyDynamicMetaObject实例,该实例提供了我们需要实现的动态行为元数据。

在MyDynamicMetaObject类中,我们重载了BindGetMember方法,该方法定义了用于动态访问成员的逻辑。这里我们使用Expression来实现了一个动态的条件语句,该条件语句尝试从Dictionary中读取属性值,如果成功则返回对应的值,否则返回默认值。

5. 总结

以上就是对于C# Dynamic之:ExpandoObject,DynamicObject,DynamicMetaObject的应用(上)的完整攻略。ExpandoObject、DynamicObject和DynamicMetaObject都是C#中实现动态类型的重要机制,使用它们可以带来更灵活的编程体验,使编程更加便捷。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C# Dynamic之:ExpandoObject,DynamicObject,DynamicMetaOb的应用(上) - Python技术站

(0)
上一篇 2023年5月31日
下一篇 2023年5月31日

相关文章

  • asp.net 使用ObjectDataSource控件在ASP.NET中实现Ajax真分页

    实现Ajax真分页的方法有很多种,其中一种是使用ObjectDataSource控件。以下是实现该功能的步骤: 步骤1:创建一个ASP.NET Web表单 首先需要创建一个ASP.NET Web表单,并在该表单中添加一个GridView控件用于显示数据。 步骤2:使用ObjectDataSource控件绑定数据 使用ObjectDataSource控件可以方…

    C# 2023年6月3日
    00
  • ASP.NET Core对不同类型的用户进行区别限流详解

    在ASP.NET Core中,您可以使用限流来控制对不同类型的用户的访问速率。本攻略将深入探讨如何使用ASP.NET Core对不同类型的用户进行区别限流,并提供两个示例说明。 区别限流 区别限流是指根据用户类型、请求类型、请求频率等因素,对不同类型的用户进行不同的限流策略。例如,对于普通用户,我们可以设置较低的请求速率限制,而对于VIP用户,我们可以设置较…

    C# 2023年5月17日
    00
  • 深入多线程之:深入分析Interlocked

    深入多线程之:深入分析Interlocked 介绍 多线程编程中,线程间的数据共享是必不可少的。但是,由于线程间数据的竞争,可能会存在数据异常的情况。而Interlocked类提供了一些原子性的操作,避免了竞争,从而保证线程间数据的准确性。 Interlocked 类及其方法 Interlocked 类的定义为:用于在多个线程之间提供原子操作的方法。 Int…

    C# 2023年6月7日
    00
  • C#中方法的详细介绍

    下面是关于“C#中方法的详细介绍”的完整攻略。 什么是方法 方法是 C# 中一种有名字的代码块,用于执行任务。方法成为代码重用的基本单元,它可以在应用程序中重复使用,其可以被传递参数和返回值。在 C# 中,方法的操作通常是与对象进行交互,也可以不直接操作对象而只执行一些函数式操作。 定义方法 定义方法需要声明其名称、参数、返回类型和方法体中的执行代码。以下是…

    C# 2023年5月31日
    00
  • .NET Core开源 DDD微服务 支持 多租户 单点登录 多级缓存、自动任务、分布式、日志、授权和鉴权 、网关 、注册与发现 系统架构 docker部署

    源代码地址https://github.com/junkai-li/NetCoreKevin基于NET6搭建跨平台DDD思想WebApi架构、IDS4单点登录、多缓存、自动任务、分布式、多租户、日志、授权和鉴权、CAP、SignalR、 docker部署  如需简约项目可直接去除项目引用 解耦设计都可以单独引用 架构默认全部引用并启动 项目启动时注意相关 R…

    C# 2023年4月27日
    00
  • ASP.NET中为DataGrid添加合计字段

    ASP.NET中的DataGrid是一个非常常用的数据显示控件,它可以对数据进行分页、排序等操作,但有时候需要在DataGrid中添加一些合计字段,以便于数据的统计分析。下面就是为DataGrid添加合计字段的完整攻略。 第一步:在DataGrid的表头或脚部添加合计字段 DataGrid表头或脚部通常是显示一些汇总性信息的地方,我们可以在这里添加合计字段。…

    C# 2023年6月8日
    00
  • Unity实现已知落点和速度自动计算发射角度

    接下来我将对“Unity实现已知落点和速度自动计算发射角度”的攻略进行详细讲解,并提供两个示例说明。 一、问题背景 在某些游戏或模拟应用中,我们需要计算发射物体的发射角度,使其能够落到指定的位置,并且在指定的速度范围内运动。这时候我们不可能通过手动调整发射角度的方式来实现目标的达成,因为如果落点或速度范围改变,我们需要重新计算发射角度,这是非常麻烦的。因此,…

    C# 2023年6月3日
    00
  • c#方法中调用参数的值传递方式和引用传递方式以及ref与out的区别深入解析

    请参考以下攻略: 什么是值传递和引用传递 在 C# 中,方法通过参数来接收外部传入的值,参数可以使用值传递或引用传递的方式进行传递。 值传递是传递值类型参数的方式,即方法接收的参数是原始值的副本,不影响原始值,例如基本类型 int、char、bool 等和结构体。 引用传递是传递引用类型参数的方式,即方法接收的参数是原始值的引用,会影响到原始值,例如数组、类…

    C# 2023年5月15日
    00
合作推广
合作推广
分享本页
返回顶部