Disons que j'ai le code suivant qui met à jour un champ d'un struct
en utilisant la réflexion. Puisque l'instance de structure est copiée dans la méthode DynamicUpdate
, it needs to be boxed to an object before being passed.Générer une méthode dynamique pour définir un champ d'une structure au lieu d'utiliser la réflexion
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);
}
}
Le code fonctionne correctement. Maintenant, disons que je ne veux pas utiliser la réflexion parce que c'est lent. Au lieu de cela, je veux générer un CIL modifiant directement le champ id
et convertir ce CIL en un délégué réutilisable (disons, en utilisant la fonction Méthode dynamique). Spécialement, je veux remplacer le code ci-dessus s/t comme ceci:
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
}
Ma question: est-il possible de mettre en œuvre CreateSetIdDelegate
d'utiliser une excepts des techniques suivantes?
- Générer CIL qui appelle le setter en utilisant la réflexion (en tant que 1er segment de code dans cette publication). Cela n'a aucun sens, étant donné que l'exigence est de se débarrasser de la réflexion, mais c'est une mise en œuvre possible, donc je viens de mentionner.
- Au lieu d'utiliser
Action<object, object>
, utilisez un délégué personnalisé dont la signature estpublic delegate void Setter(ref object target, object value)
. - Au lieu d'utiliser
Action<object, object>
, utilisezAction<object[], object>
avec le 1er élément du tableau étant l'objet cible.
La raison pour laquelle je n'aime pas 2 & 3 est parce que je ne veux pas avoir des délégués pour le poseur d'objet et compositeur de struct (et ne pas vouloir faire l'objet set-champ déléguer plus compliqué que nécessaire, par exemple Action<object, object>
). Je pense que l'implémentation de CreateSetIdDelegate
génèrerait des CIL différents selon que le type cible est struct ou object, mais je veux qu'il renvoie le même délégué offrant la même API à l'utilisateur.
utilise une struct mutable * vraiment * votre meilleure option ici? C'est presque toujours une douleur pour plusieurs raisons, et il semble que vous en rencontriez quelques-uns ... –
Avez-vous envisagé de compiler un arbre d'expression au lieu d'émettre IL? Cela devrait être beaucoup plus facile. –
@Jon: en fait, je suis en train de construire une API de réflexion rapide (http://fasterflect.codeplex.com/), de sorte que la prise en charge des opérations de réflexion par structure serait souhaitable pour certaines personnes. –