Puis-je définir une valeur sur une structure par reflection sans boxe?

En fait, j’aurais dû demander: comment puis-je faire cela et restr conforme à CLS? Parce que la seule façon pour moi de procéder est la suivante, mais utiliser __makeref , FieldInfo.SetValueDirect ou simplement System.TypedReference en général invalide la conformité CLS.

 // code illustrating the issue: TestFields fields = new TestFields { MaxValue = 1234 }; // test struct with one field FieldInfo info = fields.GetType().GetField("MaxValue"); // get the FieldInfo // actual magic, no boxing, not CLS compliant: TypedReference reference = __makeref(fields); info.SetValueDirect(reference, 4096); 

La contrepartie conforme de SetValueDirect est SetValue , mais elle prend un object comme cible. Par conséquent, ma structure est encadrée, ce qui me permet de définir une valeur sur une copie et non la variable d’origine.

Un équivalent générique de SetValue n’existe pas, à ma connaissance. Existe-t-il un autre moyen de définir le champ d’une (référence à a) struct par reflection?

Créer un wrapper compatible avec Cls sur SetValueDirect:

  var item = new MyStruct { X = 10 }; item.GetType().GetField("X").SetValueForValueType(ref item, 4); [CLSCompliant(true)] static class Hlp { public static void SetValueForValueType(this FieldInfo field, ref T item, object value) where T : struct { field.SetValueDirect(__makeref(item), value); } } 

Pour les propriétés, si vous avez les types struct et property, vous pouvez créer un délégué à partir du configurateur de propriétés. Comme vous l’avez fait remarquer, les champs n’ont pas de parameters, mais vous pouvez en créer un qui se comporte exactement de la même manière:

 delegate void RefAction(ref T1 arg1, T2 arg2); struct TestFields { public int MaxValue; public int MaxValueProperty { get { return MaxValue; } set { MaxValue = value; } } }; static class Program { static void Main(ssortingng[] args) { var propertyInfo = typeof(TestFields).GetProperty("MaxValueProperty"); var propertySetter = (RefAction)Delegate.CreateDelegate(typeof(RefAction), propertyInfo.GetSetMethod()); var fieldInfo = typeof(TestFields).GetField("MaxValue"); var dynamicMethod = new DynamicMethod(Ssortingng.Empty, typeof(void), new Type[] { fieldInfo.ReflectedType.MakeByRefType(), fieldInfo.FieldType }, true); var ilGenerator = dynamicMethod.GetILGenerator(); ilGenerator.Emit(OpCodes.Ldarg_0); ilGenerator.Emit(OpCodes.Ldarg_1); ilGenerator.Emit(OpCodes.Stfld, fieldInfo); ilGenerator.Emit(OpCodes.Ret); var fieldSetter = (RefAction)dynamicMethod.CreateDelegate(typeof(RefAction)); var fields = new TestFields { MaxValue = 1234 }; propertySetter(ref fields, 5678); fieldSetter(ref fields, 90); Console.WriteLine(fields.MaxValue); } } 

Vous ne savez pas si cela correspond à vos contraintes, mais en déclarant l’instance de struct comme étant ValueType , SetValue fonctionnera comme prévu.

  ValueType fields = new TestFields { MaxValue = 1234 }; // test struct with one field FieldInfo info = typeof(TestFields).GetField("MaxValue"); // get the FieldInfo info.SetValue(fields, 4096); Console.WriteLine(((TestFields)fields).MaxValue); // 4096 

Voir cette réponse pour plus d’informations.