1. ExpandoObject 扩展对象,运行时动态添加和移除的成员; 要用dynamic 声明,可以在编译时跳过检查,只打包信息, 在运行时在查查找并执行; 有没有javacript Prototype 的感觉?
http://msdn.microsoft.com/zh-cn/library/system.dynamic.expandoobject.aspx
2.DynamicObject 一个基类, 派生类可以override TryGetMember, TrySetMember, TryInvokeMember/TryInvoke 等方法;
http://msdn.microsoft.com/zh-cn/library/system.dynamic.dynamicobject(v=vs.110).aspx
其中关于TryInvoke可以细细品味 , 如下:
public class DynamicNumber : DynamicObject { // The inner dictionary to store field names and values. Dictionary<string, object> dictionary = new Dictionary<string, object>(); // Get the property value. public override bool TryGetMember( GetMemberBinder binder, out object result) { return dictionary.TryGetValue(binder.Name, out result); } // Set the property value. public override bool TrySetMember( SetMemberBinder binder, object value) { dictionary[binder.Name] = value; return true; } // Initializing properties with arguments' values. public override bool TryInvoke( InvokeBinder binder, object[] args, out object result) { // The invoke operation in this case takes two arguments. // The first one is integer and the second one is string. if ((args.Length == 2) && (args[0].GetType() == typeof(int)) && (args[1].GetType() == typeof(String))) { // If the property already exists, // its value is changed. // Otherwise, a new property is created. if (dictionary.ContainsKey("Numeric")) dictionary["Numeric"] = args[0]; else dictionary.Add("Numeric", args[0]); if (dictionary.ContainsKey("Textual")) dictionary["Textual"] = args[1]; else dictionary.Add("Textual", args[1]); result = true; return true; } else { // If the number of arguments is wrong, // or if arguments are of the wrong type, // the method returns false. result = false; return false; } } } class Program { static void Test(string[] args) { // Creating a dynamic object. dynamic number = new DynamicNumber(); // Adding and initializing properties. // The TrySetMember method is called. number.Numeric = 1; number.Textual = "One"; // Printing out the result. // The TryGetMember method is called. Console.WriteLine(number.Numeric + " " + number.Textual); // Invoking an object. // The TryInvoke method is called. number(2, "Two"); Console.WriteLine(number.Numeric + " " + number.Textual); // The following statement produces a run-time exception // because in this example the method invocation // expects two arguments. // number(0); } } // This code example produces the following output: // 1 One // 2 Two
3. CallSite & CallSiteBinder
http://msdn.microsoft.com/zh-cn/library/dd402827.aspx
http://msdn.microsoft.com/zh-cn/library/dd728234(v=VS.95)
5. dynamic 反编译后会是什么?
static void Main()
{
dynamic d = 5;
d.ToString();
d.ToString();
}
internal class Program { // Methods private static void Main() { object d = 5; if (<Main>o__SiteContainer0.<>p__Site1 == null) { <Main>o__SiteContainer0.<>p__Site1 = CallSite<Action<CallSite, object>>.Create(new CSharpInvokeMemberBinder(CSharpCallFlags.None, "ToString", typeof(Program), null, new CSharpArgumentInfo[] { new CSharpArgumentInfo(CSharpArgumentInfoFlags.None, null) })); } <Main>o__SiteContainer0.<>p__Site1.Target(<Main>o__SiteContainer0.<>p__Site1, d); if (<Main>o__SiteContainer0.<>p__Site2 == null) { <Main>o__SiteContainer0.<>p__Site2 = CallSite<Action<CallSite, object>>.Create(new CSharpInvokeMemberBinder(CSharpCallFlags.None, "ToString", typeof(Program), null, new CSharpArgumentInfo[] { new CSharpArgumentInfo(CSharpArgumentInfoFlags.None, null) })); } <Main>o__SiteContainer0.<>p__Site2.Target(<Main>o__SiteContainer0.<>p__Site2, d); } // Nested Types [CompilerGenerated] private static class <Main>o__SiteContainer0 { // Fields public static CallSite<Action<CallSite, object>> <>p__Site1; public static CallSite<Action<CallSite, object>> <>p__Site2; } }