Dynamic动态类型

什么是动态类型

了解什么是动态类型首先我们了解静态类型,在我们平时定义一个int i=1就是静态类型,静态类型就是我们在没有编译的时候已经明确的知道他是一个int类型,动态语言是我们在运行时才会知道的类型。所以我们在编写动态类型的时候是无法使用vs的智能提示,因为编译器也不知道他是一个什么类型。

dynamic i = 1;
Console.WriteLine(i.GetType());
dynamic str = "1";
Console.WriteLine(str.GetType());

引用一张结构图

从图中可以看出,DLR是建立在CLR的基础之上的,其实动态语言运行时是动态语言和C#编译器用来动态执行代码的库,它不具有JIT编译,垃圾回收等功能。DLR通过它的绑定器(binder)和 调用点(callsite),元对象来把代码转换为表达式树,然后再把表达式树编译为IL代码,最后 由CLR编译为本地代码(DLR就是帮助C#编译器来识别动态类型)

dynamic和var区别

var关键字不过是一个指令,它告诉编译器根据变量的初始化表达式来 推断类型。(记住var并不是类型),而dynamic是类型,但是编译时不属于CLR 类型(指的int,string,bool,double等类型,运行时肯定CLR类型中一种的),它是包含了 System.Dynamic.DynamicAttribute特性的System.Object类型,但与object又不一样,不一样主要体现在动态类型不会在编译时时执行显式转换

使用动态类型的优点

1.减少强类型的转换

2.延迟加载

3.调用C#类型中不存在的其他语言的类型

使用动态类型的缺点

1.没有智能提示

2.需要预先知道接收的数据结构

动态语言的约束

1不能用动态类型作为扩展方法的参数

2委托和动态类型不能隐式转换

3动态类型不能调用构造函数和静态方法

4类型声明和泛型类型参数

5类型声明和泛型类型参数不能声明一个基类为dynamic的类型,也不能将dynamic用于类型参数的约束,或作为类型 所实现的接口的一部分

实现动态行为

我们实现动态行为微软给我们提供了三种方式,下面我们来试一试:

使用ExpandObject

static void Main(string[] args)
{
    dynamic expand = new ExpandoObject();
    //动态为expand类型绑定属性
    expand.Name = "王麻子";
    expand.Age = 24;
    //动态为expand类型绑定方法
    expand.AddMethod = (Func<int, string>)(x => $"你传进来的是{x}");                                                
            
    //调用expand类型的属性和方法												
    Console.WriteLine($"姓名:{expand.Name}\n年龄:{expand.Age}\n绑定方法:{expand.AddMethod(666)}");
    Console.Read();	
}
姓名:王麻子
年龄:24
绑定方法:你传进来的是666

 

使用DynamicObject

class DynamicType : DynamicObject
{
    //	重写方法,													
    public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
    {
        Console.WriteLine(binder.Name + "方法被调用");
        result = null;
        return true;
    }
    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        Console.WriteLine(binder.Name + "属性被设置," + "设置的值为:" + value);
        return true;
    }
}

class Program
{
    static void Main(string[] args)
    {
        dynamic dynamicobj = new DynamicType();
        dynamicobj.CallMethod();
        dynamicobj.Name = "王麻子";
        dynamicobj.Age = "24";
        Console.Read();
    }
}
CallMethod方法被调用
Name属性被设置,设置的值为:王麻子
Age属性被设置,设置的值为:24

 

实现IDynamicMetaObjectProvider接口

class Metadynamic : DynamicMetaObject
{
    internal Metadynamic(Expression expression, DynamicType2 value) : base(expression, BindingRestrictions.Empty, value) { }
    //重写响应成员调用方法								
    public override DynamicMetaObject BindInvokeMember(InvokeMemberBinder binder, DynamicMetaObject[] args)
    {
        //获得真正的对象												
        DynamicType2 target = (DynamicType2)base.Value;
        Expression self = Expression.Convert(base.Expression, typeof(DynamicType2));
        var restrictions = BindingRestrictions.GetInstanceRestriction(self, target);
        //输出绑定方法名												
        Console.WriteLine(binder.Name + "方法被调用了");
        return new DynamicMetaObject(self, restrictions);
    }
}
public class DynamicType2 : IDynamicMetaObjectProvider
{
    public DynamicMetaObject GetMetaObject(Expression parameter)
    {
        Console.WriteLine("开始获得元数据......");
        return new Metadynamic(parameter, this);
    }
}

class Program
{
    static void Main(string[] args)
    {
        dynamic dynamicobj2 = new DynamicType2();
        dynamicobj2.Call();
        Console.Read();
    }
}
开始获得元数据......
Call方法被调用了

 

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值