I ran into a problem that I need to access to private field of a class. For example:
class MyClass
{
private string someString;
public MyClass( stri
If you are using it for unit testing, I implemented a generic version of @dcp 's answer which provides the following extras:
Code:
private const BindingFlags BindFlags = BindingFlags.Instance
| BindingFlags.Public
| BindingFlags.NonPublic
| BindingFlags.Static;
/// <summary>
/// Uses reflection to get the field value from an object.
/// </summary>
/// <param name="type">The instance type.</param>
/// <param name="instance">The instance object.</param>
/// <param name="fieldName">The field's name which is to be fetched.</param>
/// <returns>An instance of <see cref="T"/>.</returns>
internal static T GetInstanceField<T>(Type type, object instance, string fieldName)
{
var field = type.GetField(fieldName, BindFlags);
Assert.IsNotNull(field, string.Format("The field with name '{0}' does not exist in type '{1}'.", fieldName, type));
var value = field.GetValue(instance);
Assert.IsInstanceOfType(value, typeof(T), string.Format("The value of the field '{0}' is not of type '{1}'", fieldName, typeof(T)));
return (T)value;
}
You can use this Extension method.
public static class Extensions
{
public static object GetFieldValue(this object instance, string fieldName)
{
const BindingFlags bindFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
var field = instance.GetType().GetField(fieldName, bindFlags);
return field == null ? null : field.GetValue(instance);
}
}
in addition to @dcp answer, this can be a lot easier by turning it into Generic Function...
internal static T GetInstanceField<T>(object instance, string fieldName)
{
BindingFlags bindFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
| BindingFlags.Static;
FieldInfo field = type.GetField(fieldName, bindFlags);
return field.GetValue(instance);
}
If it's you're class and you want to provide access to it outside of the class, expose it via a public property:
public string SomeString { get { return someString; } }
Otherwise, don't use it outside of the class. You're not meant to.
EDIT
Based on your comment that you're actually doing QA testing on production code, I'd question the reasoning behind needing to access a private value during your testing. You really should only have to test the publicly exposed Properties/Methods to verify that everything is functioning as intended.
All that being said, if there's really no way around things you can use Reflection to get the values.
Here is a working generics version as clean as I can get it.
private static object GetInstanceField<T>(T instance, string fieldName)
{
BindingFlags bindFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
FieldInfo field = typeof(T).GetField(fieldName, bindFlags);
return field.GetValue(instance);
}
usage
var str = (string)GetInstanceField(instance, "someString");
You can't - and you're not meant to. It's private. If this is someone else's class, then clearly they don't want you to have access to that field. The fact that it's private allows them to change the implementation later - they might end up with that value as part of another variable, or renamed, or possibly gone completely if it's no longer required in order to implement the public API.
If it's your own class and you're sure you want other people to be able to access it, just expose it with a property:
public string SomeString { get { return someString; } }
EDIT: Having seen your comments, you can access the private fields with reflection... but for an acceptance test you shouldn't have to. You should be testing the public API. For unit tests it makes sense to bend the rules sometimes, and treat the class as a "white box" rather than doing "black box" testing, but for acceptance tests I would definitely stick to the public API.
If this doesn't help, I suggest you talk to the developers of the production code: explain why you want access, and ask them to expose it via a property. They could make it an internal property, and use [InternalsVisibleTo] to get access to it in your test assembly. I would personally prefer this over using reflection - otherwise if the production code changes in a perfectly valid way, your tests will fail when they shouldn't.