Giả sử tôi có mã sau cập nhật trường của phản chiếu sử dụng struct
. Vì cá thể struct được sao chép vào phương thức DynamicUpdate
, it needs to be boxed to an object before being passed.Tạo phương thức động để đặt trường của cấu trúc thay vì sử dụng phản chiếu
struct Person
{
public int id;
}
class Test
{
static void Main()
{
object person = RuntimeHelpers.GetObjectValue(new Person());
DynamicUpdate(person);
Console.WriteLine(((Person)person).id); // print 10
}
private static void DynamicUpdate(object o)
{
FieldInfo field = typeof(Person).GetField("id");
field.SetValue(o, 10);
}
}
Mã hoạt động tốt. Bây giờ, giả sử tôi không muốn sử dụng sự phản chiếu vì nó chậm. Thay vào đó, tôi muốn tạo một số CIL trực tiếp sửa đổi trường id
và chuyển đổi CIL đó thành một đại biểu có thể tái sử dụng (ví dụ: sử dụng tính năng Phương thức động). Đặc biệt, tôi muốn thay thế mã trên với s/t như thế này:
static void Main()
{
var action = CreateSetIdDelegate(typeof(Person));
object person = RuntimeHelpers.GetObjectValue(new Person());
action(person, 10);
Console.WriteLine(((Person)person).id); // print 10
}
private static Action<object, object> CreateSetIdDelegate(Type t)
{
// build dynamic method and return delegate
}
Câu hỏi của tôi: là có cách nào để thực hiện CreateSetIdDelegate
excepts từ bằng một trong những kỹ thuật sau đây?
- Tạo CIL gọi trình setter sử dụng phản chiếu (làm phân đoạn mã đầu tiên trong bài đăng này). Điều này không có ý nghĩa, vì yêu cầu là để loại bỏ sự phản chiếu, nhưng đó là một sự thực hiện có thể vì vậy tôi chỉ đề cập đến.
- Thay vì sử dụng
Action<object, object>
, hãy sử dụng đại biểu tùy chỉnh có chữ ký làpublic delegate void Setter(ref object target, object value)
. - Thay vì sử dụng
Action<object, object>
, hãy sử dụngAction<object[], object>
với phần tử thứ nhất của mảng là đối tượng mục tiêu.
Lý do tôi không thích 2 & 3 là bởi vì tôi không muốn có các đại biểu khác nhau cho các setter của đối tượng và setter của struct (cũng như không muốn làm cho các thiết lập đối tượng trường ủy nhiệm phức tạp hơn cần thiết, ví dụ: Action<object, object>
). Tôi nghĩ rằng việc thực hiện CreateSetIdDelegate
sẽ tạo ra CIL khác nhau tùy thuộc vào loại mục tiêu là cấu trúc hay đối tượng, nhưng tôi muốn nó trả về cùng một đại biểu cung cấp cùng một API cho người dùng.
là sử dụng một struct * có thể thay đổi thực sự * lựa chọn tốt nhất của bạn ở đây? Nó gần như luôn luôn là một nỗi đau vì nhiều lý do, và có vẻ như bạn đang chạy vào một số trong số họ ... –
Bạn đã xem xét biên dịch một cây biểu thức thay vì phát ra IL? Nó sẽ dễ dàng hơn nhiều. –
@Jon: thực sự tôi đang xây dựng một API phản chiếu nhanh (http://fasterflect.codeplex.com/) để hỗ trợ cho các hoạt động phản chiếu cấu trúc sẽ là mong muốn của một số người. –