欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C# Dynamic之:ExpandoObject,DynamicObject,DynamicMetaOb的应用(下)

程序员文章站 2023-12-17 12:09:46
接上文:c# dynamic关键字之:expandoobject,dynamicobject,dynamicmetaob的应用(上) 为什么tryxxx方法没有被调用?...

接上文:c# dynamic关键字之:expandoobject,dynamicobject,dynamicmetaob的应用(上)

为什么tryxxx方法没有被调用??

将dynamicproduct 中的name修饰符改为private:

private string name;

可以在trysetmember方法中设置断点,再次运行:

C# Dynamic之:ExpandoObject,DynamicObject,DynamicMetaOb的应用(下)

C# Dynamic之:ExpandoObject,DynamicObject,DynamicMetaOb的应用(下)

C# Dynamic之:ExpandoObject,DynamicObject,DynamicMetaOb的应用(下)

为什么访问修饰符是public不调用trysetmember,是private 就调用了呢??

难道是因为private抛出了异常吗??

再次看看msdn对此的trysetmember方法的解释:

msdn备注

…………….动态语言运行库 (dlr) 将首先使用语言联编程序在类中查找属性的静态定义。 如果没有此类属性,dlr 调用 trysetmember 方法。

问题的原因是这样的:首先dlr 使用语言联编程序在类中查找name的静态定义,

因为name是public,所以查找到了,然后返回,不会去调用trysetmember方法了,

但是如果name是private,那么联编程序在类中没找到name的静态定义,于是dlr尝试调用trysetmember方法。

修改trysetmember方法如下:

复制代码 代码如下:

public override bool trysetmember(setmemberbinder binder, object value)
{
    console.writeline("trysetmember被调用了,name:{0}", binder.name);
    bool result = base.trysetmember(binder, value);

    return true;
}



运行,可以发现不会抛出异常了:

C# Dynamic之:ExpandoObject,DynamicObject,DynamicMetaOb的应用(下)

总结:首先dlr会尝试查找属性的静态定义,如果没有找到则会调用相应的tryxxx 方法,如果tryxxx方法返回false,代表tryxxx方法运行失败,dlr随后会抛出异常。

为了验证是不是这样,将dynamicproduct中属性的静态定义全部注释掉,并且tryxxx方法全部返回true。完整的代码如下:

复制代码 代码如下:

class dynamicproduct : dynamicobject
{
    #region dynamicproduct 的一些属性的静态定义

        //private string name;
        //public int id { get; set; }

        //public void showproduct()
        //{
        //    console.writeline("id={0} ,name={1}", id, name);
        //}

    #endregion

    #region override dynamicobject 的方法

    public override bool trygetmember(getmemberbinder binder, out object result)
    {
        console.writeline("trygetmember被调用了,name:{0}", binder.name);
        bool tryresult = base.trygetmember(binder, out result);

        return true;
    }

    public override bool trysetmember(setmemberbinder binder, object value)
    {
        console.writeline("trysetmember被调用了,name:{0}", binder.name);
        bool tryresult = base.trysetmember(binder, value);

        return true;
    }

    public override bool tryinvoke(invokebinder binder, object[] args, out object result)
    {
        console.writeline("tryinvoke被调用了");
        bool tryresult = base.tryinvoke(binder, args, out result);

        return true;
    }

    public override bool tryinvokemember(invokememberbinder binder, object[] args, out object result)
    {
        console.writeline("tryinvokemember被调用了,name:{0}", binder.name);
        bool tryresult = base.tryinvokemember(binder, args, out result);

        return true;
    }

    #endregion
}


main方法不变:
复制代码 代码如下:

static void main(string[] args)
{
    dynamic dynproduct = new dynamicproduct();

    dynproduct.name = "n1"; //调用trysetmember方法
    dynproduct.id = 1;
    dynproduct.id = dynproduct.id + 3;
    dynproduct.showproduct();

    console.readline();
}

运行,结果如下:

C# Dynamic之:ExpandoObject,DynamicObject,DynamicMetaOb的应用(下)

d.p3 = d.m1(d.p1, d.m2(d.p2));

按照从左到右,从里到外的原则。

1:先调用d.p1,dlr会尝试调用d 的getmetaobject 方法,此方法返回一个mymetaobject对象。

接着dlr知道你调用的是一个属性,于是它调用返回的mymetaobject对象的bindgetmember 方法,

输出为getmember of property p1

2:调用d.p2,和调用d.p1 一样.

3:调用d.m2,同样dlr调用d的getmetaobject方法,返回一个mymetaobject对象,接着调用返回对象的bindinvokemember 方法。

上一篇:

下一篇: