深入理解 c# 第十四章 最终目标:动态地调用方法直到你弄到正确的名字

    class RumpelstiltskinTest
    {
        static void Main()//最终方法:动态地调用方法:直到你弄对正确的名字 
		//实现IDynamicMetaObjectProvider
        {
            Console.WriteLine("Testing first implementation");
            dynamic x = new Rumpelstiltskin("Hermione");
			//x {Chapter14.Rumpelstiltskin}
            x.Harry();
            x.Ron();
            x.Hermione();

            Console.WriteLine("Testing alternative implementation");
            // Now check the alternative implementation
            x = new Rumpelstiltskin("Ron");
            x.Harry();
            x.Ron();
            x.Hermione();
        }
    }
	
    public sealed class Rumpelstiltskin : IDynamicMetaObjectProvider
    {
        private readonly string name;
        public Rumpelstiltskin(string name)
        {
            this.name = name;
			//name "Hermione"
			//"Ron"
        }

        public DynamicMetaObject GetMetaObject(Expression expression)
		//expression {$arg0}
        {
            return new MetaRumpelstiltskin(expression, this);
        }

        private object RespondToWrongGuess(string guess)
		//guess "Harry"
        {
            Console.WriteLine("No, I'm not {0}! (I'm {1}.)",
                guess, name);
            return false;
        }

        private object RespondToRightGuess()
        {
            Console.WriteLine("Curses! Foiled again!");
            return true;
        }

        private class MetaRumpelstiltskin : DynamicMetaObject
        {
            private static readonly MethodInfo RightGuessMethod =
                typeof(Rumpelstiltskin).GetMethod("RespondToRightGuess",
                BindingFlags.Instance | BindingFlags.NonPublic);

            private static readonly MethodInfo WrongGuessMethod =
                typeof(Rumpelstiltskin).GetMethod("RespondToWrongGuess",
                BindingFlags.Instance | BindingFlags.NonPublic);

            internal MetaRumpelstiltskin
                (Expression expression, Rumpelstiltskin creator)
				//creator {Chapter14.Rumpelstiltskin}
                : base(expression, BindingRestrictions.Empty, creator)
            {}

            public override DynamicMetaObject BindInvokeMember
                (InvokeMemberBinder binder, DynamicMetaObject[] args)
            {
                Rumpelstiltskin targetObject = (Rumpelstiltskin)base.Value;
				//targetObject {Chapter14.Rumpelstiltskin}
                Expression self = Expression.Convert(base.Expression,
                    typeof(Rumpelstiltskin));
					//self {Convert($arg0)}

                Expression targetBehavior;
                if (binder.Name == targetObject.name)
                {
                    targetBehavior = Expression.Call(self, RightGuessMethod);
					//targetBehavior {Convert($arg0).RespondToWrongGuess("Harry")}
					//{Convert($arg0).RespondToWrongGuess("Ron")}
                }
                else
                {
                    targetBehavior = Expression.Call(self, WrongGuessMethod,
                        Expression.Constant(binder.Name));
                }

                var restrictions = BindingRestrictions.GetInstanceRestriction
                    (self, targetObject);
					//restrictions "{var Param_0; ... }"
                return new DynamicMetaObject(targetBehavior, restrictions);
            }
        }
    }	

  其实也没搞懂,复杂

  实现IDynamicMetaObjectProvider的难点并不是接口本身,而是构建该接口的唯一方法
所返回的DynamicMetaObject。 DynamicMetaObject有点像DynamicObject,它包含
很多方法,可以覆盖它们,并影响相应的行为。我们覆盖DynamicMetaObject.BindGetMember。
在被覆盖的方法内,它不会直接处理所需的行为,而会构建一个表达式树来描述行为以及
行为产生的环境。这种额外的间接层就是它称为元对象的原因。
  Rumpelstiltskin类型。给定的名称(存储在一个非常常见的字符串变量里)来创建
Rumpelstiltskin的实例,然后在该对象上调用方法,直到调用方法的名称与字符串相同。
  
输出
Testing first implementation
No, I'm not Harry! (I'm Hermione.)
No, I'm not Ron! (I'm Hermione.)
Curses! Foiled again!
Testing alternative implementation
No, I'm not Harry! (I'm Ron.)
Curses! Foiled again!
No, I'm not Hermione! (I'm Ron.)

猜你喜欢

转载自blog.csdn.net/eyetired/article/details/80383323