(五)动态对象

动态对象

动态语言运行时DLR

允许添加动态语言,使得C#可以支持动态语言的功能。

关于DLR的库在下列两个命名空间中

System.Dynamic;
System.Runtime.CompilerServices;

目前有IronPython,IronRuby等支持DLR的开源版本

dynamic动态类型

动态类型在编译期间会忽略类型检查,并假定动态类型的一切操作都是有效的;

运行时可抛出RuntimeBinderException类型的异常。

与var的不同点:

var是延迟确定类型,一旦确定类型不能改变。

dynamic可以在运行期间改变类型,并可以改变多次。

dynamic类型有两个限制:

动态类型不支持扩展方法,lamda表达式不支持作为动态方法调用的参数。

LINQ不支持动态对象。

static void Main(string[] args)
{
    //Console.WriteLine的参数是在运行时绑定
	dynamic a;
	a = 56;
	Console.WriteLine(a);
	Console.WriteLine(a.GetType());
	a = "12345";
	Console.WriteLine(a);
	a = new { code = "12", age = 18 };
	Console.WriteLine(a);
	Console.ReadKey();
}

ScriptRuntime

可以在应用程序中迁入脚本。

下面的示例需要使用Nuget安装IronPython

using System;
using Microsoft.Scripting.Hosting;
using IronPython.Hosting;

namespace ConsoleApp1
{
	class Program
    {
        static void Main(string[] args)
        {
			ScriptRuntime sr = Python.CreateRuntime();

			ScriptEngine se = sr.GetEngine("python");
			string content = "discCount=5\n" +
   "discAmt=.1\n" +
   "retAmt=amt\n" +
   "if x>discCount:\n" +
   "	retAmt=amt-(amt*discAmt)\n";
			ScriptSource ss = se.CreateScriptSourceFromString(content);
			ScriptScope ssc = se.CreateScope();
			ssc.SetVariable("amt", 10);
			ssc.SetVariable("x", 20);
			ss.Execute(ssc);
			dynamic d = ssc.GetVariable("retAmt");
			Console.WriteLine(d);
			Console.ReadKey();
		}
	}
}

DynamicObject

下面定义了一个动态对象,可以在运行期间动态给对象添加成员;

重写了DynamicObject的TryGetMember、TrySetMember和TryInvokeMember方法,并用Dictionary保存新添加的成员;

DynamicObject类型的动态对象可以自由的控制成员的访问

class DyObj:DynamicObject
{
	private Dictionary<string, object> dyProperty = new Dictionary<string, object>();
	public override bool TryGetMember(GetMemberBinder binder, out object result)
	{
		if(dyProperty.ContainsKey(binder.Name))
		{
			result = dyProperty[binder.Name];
			return true;
		}
		else
		{
			result = binder.Name + "成员不存在";
			return false;
		}
	}

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

	public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
	{
		dynamic method = dyProperty[binder.Name];
		result =  method((int)args[0],(int)args[1]);
		return true;
	}
}
	
class Program
{
	static void Main(string[] args)
	{
		dynamic dyObj = new DyObj();
		dyObj.Name = "zhangsan";
		dyObj.Age = 18;
		Console.WriteLine(dyObj.GetType());
		Console.WriteLine(dyObj.Name);
		Console.WriteLine(dyObj.Age);
		Func<int, int, int> func = (i, j) => i + j;
		dyObj.Add = func;
		int k = dyObj.Add(5, 6);
		Console.WriteLine(k);
		Console.ReadKey();
	}
}

ExpandoObject

下面这段代码把DyObj换成了ExpandoObject,效果是一样的;使用ExpandoObject不需要重写方法就可以动态给对象添加成员。

不需要精准控制成员的访问可以使用ExpandoObject。

class Program
{
	static void Main(string[] args)
	{
		dynamic dyObj = new ExpandoObject();
		dyObj.Name = "zhangsan";
		dyObj.Age = 18;
		Console.WriteLine(dyObj.GetType());
		Console.WriteLine(dyObj.Name);
		Console.WriteLine(dyObj.Age);
		Func<int, int, int> func = (i, j) => i + j;
		dyObj.Add = func;
		int k = dyObj.Add(5, 6);
		Console.WriteLine(k);
		dyObj.Skill = new List<string>();
		dyObj.Skill.Add("java");
		dyObj.Skill.Add("C#");
		dyObj.Skill.Add("C");
		foreach (string skill in dyObj.Skill)
			Console.WriteLine(skill);
		Console.ReadKey();
	}
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值