Đây là phương pháp của tôi để truyền một đối tượng nhưng không phải là một biến loại chung, thay vì System.Type
động:
Tôi tạo một biểu thức lambda trong thời gian chạy bằng cách sử dụng System.Linq.Expressions
, loại bỏ hộp Func<object, object>
đầu vào của nó, thực hiện chuyển đổi loại mong muốn sau đó đưa ra kết quả được đóng hộp. Một loại mới không chỉ cần thiết cho tất cả các loại được truyền tới, mà còn cho các loại được truyền (vì bước unboxing). Việc tạo các biểu thức này rất tốn thời gian, vì sự phản chiếu, biên dịch và xây dựng phương thức động được thực hiện dưới mui xe. May mắn là một khi được tạo, các biểu thức có thể được gọi liên tục và không có chi phí cao, vì vậy tôi lưu trữ từng bộ đệ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);
}
Lưu ý rằng đây không phải là phép thuật. Việc truyền không xảy ra trong mã, giống như với dynamic
từ khóa, chỉ có dữ liệu cơ bản của đối tượng được chuyển đổi. Tại thời điểm biên dịch, chúng ta vẫn còn phải cố gắng tìm ra chính xác loại đối tượng của chúng ta có thể là gì, làm cho giải pháp này không thực tế. Tôi đã viết điều này như một hack để gọi các toán tử chuyển đổi được xác định bởi các loại tùy ý, nhưng có lẽ ai đó ngoài kia có thể tìm thấy một trường hợp sử dụng tốt hơn.