C#: Dynamic runtime cast

前端 未结 9 2120
情深已故
情深已故 2020-11-27 03:50

I would like to implement a method with the following signature

dynamic Cast(object obj, Type castTo);

Anyone know how to do that? obj defi

相关标签:
9条回答
  • 2020-11-27 04:10

    The opensource framework Dynamitey has a static method that does late binding using DLR including cast conversion among others.

    dynamic Cast(object obj, Type castTo){
        return Dynamic.InvokeConvert(obj, castTo, explict:true);
    }
    

    The advantage of this over a Cast<T> called using reflection, is that this will also work for any IDynamicMetaObjectProvider that has dynamic conversion operators, ie. TryConvert on DynamicObject.

    0 讨论(0)
  • 2020-11-27 04:16

    This should work:

    public static dynamic Cast(dynamic obj, Type castTo)
    {
        return Convert.ChangeType(obj, castTo);
    }
    

    Edit

    I've written the following test code:

    var x = "123";
    var y = Cast(x, typeof(int));
    var z = y + 7;
    var w = Cast(z, typeof(string)); // w == "130"
    

    It does resemble the kind of "typecasting" one finds in languages like PHP, JavaScript or Python (because it also converts the value to the desired type). I don't know if that's a good thing, but it certainly works... :-)

    0 讨论(0)
  • 2020-11-27 04:17

    I realize this has been answered, but I used a different approach and thought it might be worth sharing. Also, I feel like my approach might produce unwanted overhead. However, I'm not able to observer or calculate anything happening that is that bad under the loads we observe. I was looking for any useful feedback on this approach.

    The problem with working with dynamics is that you can't attach any functions to the dynamic object directly. You have to use something that can figure out the assignments that you don't want to figure out every time.

    When planning this simple solution, I looked at what the valid intermediaries are when attempting to retype similar objects. I found that a binary array, string (xml, json) or hard coding a conversion (IConvertable) were the usual approaches. I don't want to get into binary conversions due to a code maintainability factor and laziness.

    My theory was that Newtonsoft could do this by using a string intermediary.

    As a downside, I am fairly certain that when converting the string to an object, that it would use reflection by searching the current assembly for an object with matching properties, create the type, then instantiate the properties, which would require more reflection. If true, all of this can be considered avoidable overhead.

    C#:

    //This lives in a helper class
    public static ConvertDynamic<T>(dynamic data)
    {
         return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(Newtonsoft.Json.JsonConvert.SerializeObject(data));
    }
    
    //Same helper, but in an extension class (public static class),
    //but could be in a base class also.
    public static ToModelList<T>(this List<dynamic> list)
    {
        List<T> retList = new List<T>();
        foreach(dynamic d in list)
        {
            retList.Add(ConvertDynamic<T>(d));
        }
    }
    

    With that said, this fits another utility I've put together that lets me make any object into a dynamic. I know I had to use reflection to do that correctly:

    public static dynamic ToDynamic(this object value)
    {
        IDictionary<string, object> expando = new ExpandoObject();
    
        foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(value.GetType()))
            expando.Add(property.Name, property.GetValue(value));
    
        return expando as ExpandoObject;
    }
    

    I had to offer that function. An arbitrary object assigned to a dynamic typed variable cannot be converted to an IDictionary, and will break the ConvertDynamic function. For this function chain to be used it has to be provided a dynamic of System.Dynamic.ExpandoObject, or IDictionary<string, object>.

    0 讨论(0)
提交回复
热议问题