I am working on a project where a field name from XML is loaded and the field with that name is returned 开发者_JAVA百科and added to the current object. The problem is that FieldInfo.GetValue seems to return the current value of the field, not a reference. Is there any way to get around this?
No unfortunately there is not. The design of FieldInfo.GetValue
is to provide the value and not a reference. There is no other suitable method on FieldInfo
to provide a reference either.
One reason why is that doing so would be simply unsafe. Imagen the scenario where the object is a struct
on the stack. If a FieldInfo
could provide a reference to a field of that struct
then it would be supplying a reference to a piece of the stack which could go away at any moment. Reading or writing that reference after the stack went away would be incorrect and a type safety violation.
You can get it with an expression tree. This works for NativeAOT too!
private delegate ref int GetRefDelegate(MyClass obj);
private static ref int EchoRef(ref int x)
{
return ref x;
}
private class
{
public in MyField;
}
public static Main()
{
var objParam = Expression.Parameter(typeof(Test), "obj");
var echoRef = Expression.Lambda<GetRefDelegate>(
Expression.Call(
typeof(Program).GetMethod(nameof(EchoRef), BindingFlags.Static | BindingFlags.NonPublic),
new Expression[]
{
Expression.Field(objParam, typeof(Test).GetField("MyField"))
}
),
false,
new ParameterExpression[] { objParam }
);
var obj = new MyClass();
ref int gotRef = ref echoRef.Compile()(obj);
}
For some reason, the expression tree compiler can understands that a field reference is needed with a method invocation with a reference parameter, but it cannot recognize the same when the return type is with a reference parameter. That's why you need to invoke the dummy EchoRef
method.
精彩评论