2009-12-27 4 views
6

J'ai une instance d'une classe, je veux changer un membre de données d'objet de cette instance seulement avec un autre objet du même type (échange), dû à mes contraintes système, je ne peux pas utiliser les opérateurs =, new ou setter.C# Réflexion - changer la valeur d'un champ d'une variable

Fondamentalement, je voudrais changer la valeur d'un champ d'une variable, le champ est un objet contenu dans un autre objet - la variable que son instance j'ai.

est-ce possible en utilisant la réflexion? Si oui, quelqu'un peut-il me donner des instructions de base?

Merci Yoav

+0

Pouvez-vous partager un peu de code, s'il vous plaît ? –

+0

La valeur que vous souhaitez modifier une propriété ou un champ? Si c'est une propriété, connaissez-vous le nom du champ qui se trouve derrière? - Fondamentalement, si une propriété n'a pas d'accesseur défini, vous ne pouvez pas changer sa valeur (même en utilisant la réflexion), cependant s'il y a un champ derrière, même s'il est privé, vous pouvez (habituellement) le changer en utilisant la réflexion. Dans certains cas (je ne rappelle pas la référence), vous pouvez même refuser l'accès à la réflexion à des champs privés. –

Répondre

13

Oui, il est possible.

En bref, faire quelque chose comme

Type typeInQuestion = typeof(TypeHidingTheField); 
FieldInfo field = typeInQuestion.GetField("FieldName", BindingFlags.NonPublic | BindingFlags.Instance); 
field.SetValue(instanceOfObject, newValue); 

pour changer la valeur d'un champ caché (privé/protégé/interne). Utilisez le FieldInfo.GetValue(...) correspondant pour lire; combiner les deux trivialement pour obtenir votre opération de permutation désirée. Ne pas me tenir à BindingFlags (je semble toujours se tromper sur la première tentative) ou la exacte syntaxe, mais c'est fondamentalement cela.

Regardez System.Reflection pour référence.

+0

BindingFlags semble bien, mais peut également inclure Public ... BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance – David

4

Si vous utilisez .NET 3.5, vous pouvez utiliser ma bibliothèque open-source, Fasterflect, pour répondre à cette question avec le code suivant:

typeof(MyType).SetField("MyField", anotherObject); 

Lorsque vous utilisez Fasterflect, vous n'avez pas à se soucier de la spécification BindingFlags à droite et l'implication des performances (comme lors de l'utilisation de la réflexion).

0

en vb avec les génériques, mais la gestion des erreurs rudimentaire:

Module somereflectionops 
    Function GetFieldValue(Of OBTYPE, FIELDTYPE)(instance As OBTYPE, fieldname As String, Optional specbindingflags As BindingFlags = BindingFlags.NonPublic Or BindingFlags.Instance) As FIELDTYPE 
     Dim ot As Type = GetType(OBTYPE) 
     Dim fi As FieldInfo 
     Try 
      fi = ot.GetField(fieldname, BindingFlags.Default Or specbindingflags) 
      If fi Is Nothing Then Return Nothing 
      Return fi.GetValue(instance) 
     Catch ex As Exception 
      Return Nothing 
     End Try 
    End Function 

    Function SetFieldValue(Of OBTYPE, FIELDTYPE)(instance As OBTYPE, fieldname As String, value As FIELDTYPE, Optional specbindingflags As BindingFlags = BindingFlags.NonPublic Or BindingFlags.Instance) As Boolean 
     Dim ot As Type = GetType(OBTYPE) 
     Dim fi As FieldInfo 
     Try 
      fi = ot.GetField(fieldname, BindingFlags.Default Or specbindingflags) 
      If fi Is Nothing Then Return false 
      fi.SetValue(instance, value) 
      Return True 
     Catch ex As Exception 
      Return False 
     End Try 
    End Function 
End Module 

utilisation: SetFieldValue (de cartonclass, entier) (cartonyoudropped, "survivingeggcount", 3)

Questions connexes