Aquí está mi método para convertir un objeto pero no a una variable de tipo genérico, sino a una System.Type
dinámica:
Creo una expresión lambda en tiempo de ejecución usando System.Linq.Expressions
, de tipo Func<object, object>
, que desempaqueta su entrada, realiza la conversión de tipo deseada y luego da el resultado encuadrado. Se necesita uno nuevo no solo para todos los tipos que se lanzan, sino también para los tipos que se lanzan (debido al paso de desempaquetado). La creación de estas expresiones requiere mucho tiempo, debido a la reflexión, la compilación y la construcción dinámica de métodos que se realiza bajo el capó. Afortunadamente, una vez creadas, las expresiones se pueden invocar repetidamente y sin sobrecarga, por lo que guardo en caché cada una.
private static Func<object, object> MakeCastDelegate(Type from, Type to)
{
var p = Expression.Parameter(typeof(object)); //do not inline
return Expression.Lambda<Func<object, object>>(
Expression.Convert(Expression.ConvertChecked(Expression.Convert(p, from), to), typeof(object)),
p).Compile();
}
private static readonly Dictionary<Tuple<Type, Type>, Func<object, object>> CastCache
= new Dictionary<Tuple<Type, Type>, Func<object, object>>();
public static Func<object, object> GetCastDelegate(Type from, Type to)
{
lock (CastCache)
{
var key = new Tuple<Type, Type>(from, to);
Func<object, object> cast_delegate;
if (!CastCache.TryGetValue(key, out cast_delegate))
{
cast_delegate = MakeCastDelegate(from, to);
CastCache.Add(key, cast_delegate);
}
return cast_delegate;
}
}
public static object Cast(Type t, object o)
{
return GetCastDelegate(o.GetType(), t).Invoke(o);
}
Tenga en cuenta que esto no es mágico. La conversión no se produce en el código, como ocurre con la dynamic
palabra clave, solo se convierten los datos subyacentes del objeto. En el momento de la compilación, todavía tenemos que determinar minuciosamente exactamente qué tipo de objeto podría ser, lo que hace que esta solución sea poco práctica. Escribí esto como un truco para invocar operadores de conversión definidos por tipos arbitrarios, pero tal vez alguien por ahí pueda encontrar un mejor caso de uso.