在运行时隐式地转换动态对象

时间:2014-08-08 20:30:42

标签: c# dynamic casting

说我有以下代码:

class MyField : DynamicObject 
{
     public dynamic Value { get; private set; }

     public override bool TryConvert(ConvertBinder binder, out object result)
     {
         result = binder.Type == Value.GetType() ? Value : null;
         return result != null;
     }

     public MyField(dynamic v) 
     {
          Value = v;
     }
}
// ...
public static class Program
{
    static void doSomething(ulong address) { /* ... */ }

    public void Main(string[] args)
    {
         dynamic field = new MyField((ulong)12345);
         doSomething(field); // fails as field is not a ulong.
         doSomething((ulong)field); // succeeds as field can be casted to a ulong.
         ulong field2 = field; // also succeeds
    }
}

有没有办法让第一次调用doSomething成功?我正在编写一个库来读取使用序列化C风格结构的特定文件格式;读取文件需要读取这些保存的结构定义,然后使用文件其余部分中包含的数据“填充”它们。我有一个“结构”DynamicObject类(支持点符号访问)和“字段”DynamicObject类,这对于保存字段内容的其他信息是必要的;虽然我可以摆脱它,但它会使某些其他操作更加困难。我想做的只是“假装”MyField是某种类型(好吧,技术上只是任何内置基元或基元数组,包括2D数组)并隐式地将其转换为该类型。但是,如果field与所需类型不匹配,则运行时无法尝试将field隐式转换为基础方法签名所需的类型。

2 个答案:

答案 0 :(得分:1)

在Greg的回答中,我想出了一个让运行时感到满意的解决方案。这不是我原本想要的,但它似乎是最好的解决方案。

因为我的源代码中已经有一个很大的if-else树,其中我获取了一个字节数组并将它们解释为实际值类型,实际上我的当前源确实使用了基础泛型MyField<T> ,所以这很好。我不记得为什么我希望MyField首先成为dynamic

无论如何,这是一个经过修改的解决方案。

class MyField<T>
{
    public dynamic Value { get; private set; }

    public MyField(dynamic v) { Value = v; }

    public static implicit operator T(MyField field)
    {
        return (T)field.Value;
    }
}

我一直想要让运行时只是弄清楚在运行时将MyField转换成需要什么,但我想这不是什么大不了的事。如果有人想出更好的东西,请告诉我。我打算在此期间保持这个问题。

答案 1 :(得分:0)

您可能想要查看 Generics 。加上interface可能会使动态使用更加可行。

public interface Helper <TInput, TOutput>
{
     <TOutput> DoSomething(TInput input);
}

因此,当您将此interface与类一起使用时,您将为输入和输出实现类型。这将给你相当大的灵活性,这应该避免你之前提到的那些cast。一个小例子,我的意思是你可以根据需要调整它,但我仍然不明白你真正想做的事情。