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

本文关键字:转换 动态 对象 运行时 | 更新日期: 2023-09-27 18:17:16

假设我有以下代码:

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转换为基础方法签名所需的类型。

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

根据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;
    }
}

我一直想要运行时只是找出它需要cast MyField在运行时,但我想这不是一个大的交易。如果有人想出更好的办法,请告诉我。在此期间,我将保留这个问题。

您可能想要查看泛型。与interface相结合可以使动态使用更加可行。

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

因此,当您将此interface与类一起使用时,您将为输入和输出实现类型。这将为您提供相当大的灵活性,这应该避免您之前提到的cast。举个小例子,我的意思是你可以根据需要进行调整,但我还是不明白你到底想做什么