İşte benim nesne bir System.Type
dinamik değil, genel bir tür değişkenine değil, bir nesne döküm yöntemi :
Girdi kutusundan, türünü istenen tür dönüşüm gerçekleştirir System.Linq.Expressions
türünü kullanarak türünü kullanarak çalışma zamanında lambda ifade oluşturmak Func<object, object>
sonra sonuç kutulu verir. Sadece dökülen tüm tipler için değil, aynı zamanda dökülen tipler için de (kutu açma adımı nedeniyle) yeni bir tane gereklidir. Bu ifadelerin oluşturulması, kaputun altında yapılan yansıma, derleme ve dinamik yöntem oluşturma nedeniyle oldukça zaman alıcıdır. Neyse ki oluşturulduktan sonra, ifadeler tekrar tekrar ve yüksek ek yük olmadan çağrılabilir, bu yüzden her birini önbelleğe alırım.
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);
}
Bunun sihir olmadığını unutmayın. Kodda, dynamic
anahtar kelimeyle olduğu gibi, yalnızca nesnenin temel verileri dönüştürülür. Derleme zamanında, nesnemizin ne tür olabileceğini titizlikle anlamaya devam ediyoruz ve bu çözümü pratik yapmıyoruz. Bunu rastgele türler tarafından tanımlanan dönüşüm operatörlerini çağırmak için bir hack olarak yazdım, ancak belki de birileri daha iyi bir kullanım durumu bulabilir.