使用动态对象
使用动态对象进行编程,开发人员可以用一个动态调度机制对设想的操作进行编码。"运行时" 会在程序执行时对这个机制进行解析,而不是由编译器在编译时验证和绑定。一个简单的实例 来自MSDN
using System;
namespace DynamicExamples
{
class Program
{
static void Main(string[] args)
{
ExampleClass ec = new ExampleClass();
Console.WriteLine(ec.exampleMethod(10));
Console.WriteLine(ec.exampleMethod("value"));
//************************** Point 1 **************************
// The following line causes a compiler error because exampleMethod
// takes only one argument.
//Console.WriteLine(ec.exampleMethod(10, 4));
//***************************************************************
dynamic dynamic_ec = new ExampleClass();
Console.WriteLine(dynamic_ec.exampleMethod(10));
//************************** Point 2 **************************
// Because dynamic_ec is dynamic, the following call to exampleMethod
// with two arguments does not produce an error at compile time.
// However, itdoes cause a run-time error.
//Console.WriteLine(dynamic_ec.exampleMethod(10, 4));
//***************************************************************
Console.ReadKey();
}
}
class ExampleClass
{
//static dynamic field;
dynamic prop { get; set; }
public dynamic exampleMethod(dynamic d)
{
dynamic local = "Local variable";
int two = 2;
if (d is int)
{
return local;
}
else
{
return two;
}
}
}
}
注意注释的重点的两行,虽然被注释了但意义重大。
在point 1使用的是 基础类型,如果发现被调用的类的成员不存在 编译时就会 报错。在point 2使用的是 dynamic类型,如果发现被调用的类的成员不存在会在 运行时抛出 异常。
如果一变量声明为dynamic,编译时不会检查指定的成员是否存在,甚至不会检查dynamic的基础类型是什么。
但dynamic类型在运行时发现调用的成员不存在,则会引发 Microsoft.CSharp.RuntimeBinder.RuntimeBinderException。
使用dynamic的好处
这里有一个解析XML文件的小例子,它包含了两部分,自定义的一个dynamic类型和使用它,尤其在使用它的时候,他比正常的解析XML文件的代码要简洁。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Dynamic;
using System.Xml.Linq;
namespace dyanmic_parse_xml
{
public class DynamicXml : DynamicObject
{
private XElement Element{get; set;}
public DynamicXml(XElement element)
{
Element = element;
}
public static DynamicXml Parse(string str)
{
return new DynamicXml(XElement.Parse(str));
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
bool success = false;
result = null;
XElement firstDescendant = Element.Descendants(binder.Name).FirstOrDefault();
if (firstDescendant != null)
{
if (firstDescendant.Descendants().Count() > 0)
{
result = new DynamicXml(firstDescendant);
}
else
{
result = firstDescendant.Value;
}
success = true;
}
return success;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
bool success = false;
XElement firstDescendant = Element.Descendants(binder.Name).FirstOrDefault();
if (firstDescendant != null)
{
if (value.GetType() == typeof(XElement))
{
firstDescendant.ReplaceWith(value);
}
else
{
firstDescendant.Value = value.ToString();
}
success = true;
}
return success;
}
}
}
Program.cs
using System;
using System.Linq;
using System.Xml.Linq;
namespace dyanmic_parse_xml
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Use legacy way");
Console.WriteLine("=========================================================");
XElement person = XElement.Parse(@"<Person>
<FirstName>Inigo</FirstName>
<LastName>Montoya</LastName>
</Person>");
Console.WriteLine("{0} {1}", person.Descendants("FirstName").FirstOrDefault().Value,
person.Descendants("LastName").FirstOrDefault().Value);
Console.WriteLine("\nUse dynamic way");
Console.WriteLine("=====================================&#