实现任何方式'是'/'为'动态或至少是假的呢? [英] Any way to implement 'is'/'as' for dynamic or at least fake it?

查看:96
本文介绍了实现任何方式'是'/'为'动态或至少是假的呢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个类型的 ConfigValue 是通过 IDynamicMetaObjectProvider 的实施和定制<$ C $暴露了一个动态界面C> DynamicMetaObject 实例。

I have a type ConfigValue that exposes a dynamic interface via an implementation of IDynamicMetaObjectProvider and custom DynamicMetaObject instance.

此类型的实例可以看出,当然,因为它是天然型 - 类​​似于一个XML元素 - 但它也可以被看作是任何其它的对象类型的实例,根据XML,什么的内容类型的对象它建立的(这一点以前的我建立了一个专用的IOC)。

An instance of this type can be seen, of course, as it's native type - analogous to an XML Element - but it can also be seen as an instance of any other object type, according to the contents of the XML and what kind of object it builds (it's a proprietary IOC built by little old me).

于是

<value>10</value>

可以看到,作为一个 ConfigValue ,也可能是一个字符串等转换是通过隐性或显性投来实现,所指定的调用语言。该XML变得更加复杂,因为你可以解雇构造函数,方法,属性获取等。

Can be seen as a ConfigValue but also potentially a string, short, double etc. Conversion is achieved by implicit or explicit cast, as specified by the calling language. The XML gets more complicated because you can fire constructors, methods, property gets etc.

要做到这一点,我已经重写的 BindConvert 成员 DynamicMetaObject 键入 - 如果转换是不支持在运行时, ConfigValue 对象,然后发生运行时错误(这是罚款)。

To achieve this, of course, I have overriden the BindConvert member of the DynamicMetaObject type - and if the conversion is unsupported by the ConfigValue object at runtime, then a runtime error occurs (which is fine).

我刚开始写一张code其中这将是巨大的,如果我可以做一个安全的强制转换为目标类型,但如果不行退回到其他逻辑 - 这类似于:

I've just started writing a piece of code where it would be great if I could do a safe cast to the target type, but if that doesn't work fallback to some other logic - analogous to:

public DesiredType Foo(dynamic d)
{
  DesiredType dt = d as dt;
  if(dt != null)
    return dt;
  //TODO: Fallback logic to build dt from d
}

不过,C#至少(也可能是所有动态感知语言我敢肯定)不会发出任何动态的作为,或结合'是'业务; presumably因为 DynamicMetaObject 不具备这样的测试方法。从而型式试验刚刚执行在其上,在这种情况下,总是失败的静态类型信息。

But, C# at least (and probably all dynamic-aware languages I'm sure) doesn't emit any dynamic binding for the 'as' or 'is' operations; presumably because DynamicMetaObject doesn't have a method for such a test. Thus the type test is just performed on the static type information which, in this case, always fails.

因此​​我不得不依靠比较难看:

As a result I'm having to rely on the rather ugly:

public DesiredType Foo(dynamic d)
 {
   try
   {
      return (DesiredType)d;
   }
   catch(Exception)
   {
     //TODO: fallback logic
   }
 }

任何想法如何,我可以避开的try / catch /一饮而尽模式在这里!?最好我能想到的是什么东西 DynamicMetaObject 的顶部;但随后进行查询为先,然后才再次被质疑为型式检验的;这只是要进一步引爆code了!

Any ideas how I can avoid the try/catch/gulp pattern here!? The best I can think of is something on top of DynamicMetaObject; but then that has to be queried for first, before then being queried again for the type test; which is just going to explode the code up even further!

推荐答案

我不认为这是可能的。

举个例子,这code:

Take for example, this code:

class Program
{
    static void Main(string[] args)
    {
        dynamic d = new object();

        var x = (Program)d;
        Console.WriteLine(x);

        var y = d as Program;
        Console.WriteLine(y);

        var z = d is Program;
        Console.WriteLine(z);
    }
}

如果我们反编译使用反射它,我们看到,中投能够通过动态类型被截获的唯一原因是,C#编译器做了很多额外的工作,以支持它:

If we decompile it using Reflector we see that the only reason that the cast is able to be intercepted by the dynamic type is that the C# compiler does a lot of extra work in order to support it:

class Program
{
    private static void Main(string[] args)
    {
        object d = new object();
        if (<Main>o__SiteContainer0.<>p__Site1 == null)
        {
            <Main>o__SiteContainer0.<>p__Site1 = CallSite<Func<CallSite, object, Program>>.Create(Binder.Convert(CSharpBinderFlags.ConvertExplicit, typeof(Program), typeof(Program)));
        }
        Console.WriteLine(<Main>o__SiteContainer0.<>p__Site1.Target(<Main>o__SiteContainer0.<>p__Site1, d));

        Program y = d as Program;
        Console.WriteLine(y);

        bool z = d is Program;
        Console.WriteLine(z);
    }
}

相反,通话只是编译成IL指令,与不加魔法C#编译器。

In contrast, the as and is calls are simply compiled down to IL instructions, with no added magic from the C# compiler.

这适合在与正常的铸造操作为好;使用,而不是一个演员不会执行任何转换蒙上,让永远不变的基础对象的类型。

This fits in with the normal casting operators as well; using as rather than a cast will not perform any conversion casts, so will never change the type of the underlying object.

这篇关于实现任何方式'是'/'为'动态或至少是假的呢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆