This returns all non-public instance properties:
var instanceNonPublic = currentType.GetProperties (BindingFlags.Instance |
BindingFlags.NonPublic);
But is there any way to determine which access modifier applies to each property? private, internal or protected?
Since properties are made of get method and set method you can iterate them and filter the relevant PropertyInfos using their get and set methods' access modifiers:
var instancePrivate = currentType.GetProperties(BindingFlags.Instance |
BindingFlags.NonPublic)
.Where(x => x.GetMethod.IsPrivate &&
x.SetMethod.IsPrivate);
Those are the interesting access modifiers:
IsPrivate indicates that the method is private.
IsFamily indicates that the method is protected.
IsAssembly indicates that the method is internal.
Other way to elegantly set the filter is using FindMembers:
public void YourMethod()
{
...
var instancePrivate = currentType.FindMembers(MemberTypes.Property,
BindingFlags.Instance |
BindingFlags.NonPublic,
PrivateMemberFilter, null);
.OfType<PropertyInfo>();
...
}
static readonly MemberFilter PrivatePropertyFilter = (objMemberInfo, objSearch) =>
{
PropertyInfo info = (objMemberInfo as PropertyInfo);
if (info == null)
{
return false;
}
return info.GetMethod.IsPrivate && info.SetMethod.IsPrivate;
};
Related
I'm trying to mod Planetbase and I have to access protected static List<Character> mCharacters = new List<Character>(); inside public abstract class Character in Planetbase namespace. Here is my code:
FieldInfo characters = typeof(Character).GetField("mCharacters", BindingFlags.NonPublic | BindingFlags.Instance);
carriedResources = Character.characters.Where(x => x.getLoadedResource() != null)
.ToDictionary(y => y, x => x.getLoadedResource()); // Get all carried resources across all characters
However I'm getting the "Character does not contain the definition for characters" error despite writing a method to access it. No idea what I'm doing wrong.
The BindingFlags you are using are not correct. What you need is BindingFlags.NonPublic | BindingFlags.Static. You can find out more about this enumeration here.
These are some of the most used binding flags when one would search for any type member (field, property, method, etc.):
BindingFlags.Public specifies that public members are to be included in the search.
BindingFlags.NonPublic specifies that non-public members are to be included in the search.
BindingFlags.Instance specifies that instance members are to be included in the search.
BindingFlags.Static specifies that static members are to be included in the search.
Update:
I just noticed that you are not accessing the field information appropriately. After you have the field info, you can access the underlying value like this:
FieldInfo field = typeof(Character).GetField("mCharacters", BindingFlags.NonPublic | BindingFlags.Instance);
var value = field.GetValue(__character_instance__);
The retrieved value will be of type object so you have to safely convert it to the appropriate type.
So if I have this class:
public class Person
{
private readonly string _name;
public Person(string name)
{
this._name = name;
}
}
I can access the field data like this:
var person = new Person("Tony Troeff");
var field = typeof(Person).GetField("_name", BindingFlags.NonPublic | BindingFlags.Instance);
var fieldValue = field.GetValue(person) as string;
I use this code:
BindingFlags flags= BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public;
PropertyInfo prop = myObj.GetProperty("Age", flags);
prop is not null. However, when I try to get all properties from myObj:
foreach(MemberInfo e in myObj.GetType().GetMembers( flags) ) { //neither GetProperties helps
Console.WriteLine(e.Name);
}
that property (Age) is not listed. I can't understand how this happens.
The dfiference between Type.GetProperty and Type.GetMembers is that both return private properties/members(which include properties), but GetMembers only of this type and not from base types whereas GetProperty also returns private properties of base types.
GetProperty:
Specify BindingFlags.NonPublic to include non-public properties (that
is, private, internal, and protected properties) in the search.
GetMembers:
Specify BindingFlags.NonPublic to include non-public members (that is,
private, internal, and protected members) in the search. Only
protected and internal members on base classes are returned; private
members on base classes are not returned.
So i guess that Age is an inherited property. If you would add BindingFlags.DeclaredOnly the result should be the same, you wouldn't see Age.
If you want to force GetMembers to include also private members of base types, use following extension method that loops all base types:
public static class TypeExtensions
{
public static MemberInfo[] GetMembersInclPrivateBase(this Type t, BindingFlags flags)
{
var memberList = new List<MemberInfo>();
memberList.AddRange(t.GetMembers(flags));
Type currentType = t;
while((currentType = currentType.BaseType) != null)
memberList.AddRange(currentType.GetMembers(flags));
return memberList.ToArray();
}
}
Now your BindingFlags work already and even a private "inherited" Age property is returned:
MemberInfo[] allMembers = myObj.GetType().GetMembersInclPrivateBase(flags);
I need to find property inside of generic type. This is an old way (and since my code is dedicated for WinRT I believe I need another approach):
PropertyInfo pi = typeof(TRp).GenericTypeArguments[0].GetProperty(idField, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
I need to achieve the same result using GetRuntimeProperties. This is my approach:
PropertyInfo pi = typeof(TRp).GenericTypeArguments[0].GetRuntimeProperties().Single(p => p.Name.ToUpper() == idField.ToUpper()...
as you can see I implemented IgnoreCase in a custom way, probably it can be done better?
How can I implement remaining BindingFlags?
Thank you!
You actually dont need to. This is how Type.GetRuntimeProperties is implemented:
public static IEnumerable<PropertyInfo> GetRuntimeProperties(this Type type)
{
CheckAndThrow(type);
IEnumerable<PropertyInfo> properties = type.GetProperties(everything);
return properties;
}
Where everything is defined as following:
private const BindingFlags everything = BindingFlags.Instance |
BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.Static;
Which means it will already look for your required flags.
Edit:
If you want to specify BindingFlags yourself, you can write your own custom extension method:
public static class TypeExtensions
{
public static IEnumerable<PropertyInfo> GetAllProperties(this TypeInfo type,
BindingFlags bindingFlags)
{
var propertyInfos = type.GetProperties(bindingFlags);
var subtype = type.BaseType;
if (subtype != null)
list.AddRange(subtype.GetTypeInfo().GetAllProperties(bindingFlags));
return propertyInfos.ToArray();
}
}
Note this hasn't been tested. It is merely an attempt to show you that you can do it yourself.
I want to know what is fastest way to get value (only for this problem) from an object`s property ?
after some searching I saw a post from #MarkGravell in this site
He wrote this code :
using System;
using System.Reflection;
using System.Reflection.Emit;
public class Foo
{
public Foo(int bar)
{
Bar = bar;
}
private int Bar { get; set; }
}
static class Program {
static void Main()
{
var method = new DynamicMethod("cheat", typeof(int),
new[] { typeof(object) }, typeof(Foo), true);
var il = method.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Castclass, typeof(Foo));
il.Emit(OpCodes.Callvirt, typeof(Foo).GetProperty("Bar",
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
).GetGetMethod(true));
il.Emit(OpCodes.Ret);
var func = (Func<object, int>)method.CreateDelegate(
typeof(Func<object, int>));
var obj = new Foo(123);
Console.WriteLine(func(obj));
}
}
OR
var method = typeof(Foo).GetProperty("Bar",
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.GetGetMethod(true);
var func = (Func<Foo, int>)
Delegate.CreateDelegate(typeof(Func<Foo, int>), method);
I changed it to
var pt = propertyInfo.PropertyType; // I dont know what is Type
var method = pt.GetProperty("Bar",
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
.GetGetMethod(true);
var func = (Func<Foo, object>) // I dont know what is return type so set object !!!
Delegate.CreateDelegate(typeof(Func<Foo, object>), method); // I want get value as object ?!!!
return func(entity).ToString(); // cast return value to string
but I got an exception
Cannot bind to the target method because its signature or security transparency is not compatible with that of the delegate type.
I dont know what is my property type It can be anything How customize code for this purpose ?
If anyone can help me in better way (fastest way) without property Type restriction please introduce it
The Delegate.CreateDelegate will not work in this case, because you have to cast the resulting delegate to some known type, otherwise all you have is DynamicInvoke which is not better than direct invocation of PropertyInfo (see here explanation by Marc Gravell).
The most generic way I've seen which does not involve lambda expressions (like
Sriram Sakthivel suggested) is shown by Jon Skeet here. Building on his approach and the fact we can get the actual property return type from PropertyInfo, we can invent something custom-tailored for properties invocation.
First, we define an interface:
public interface IPropertyCallAdapter<TThis>
{
object InvokeGet(TThis #this);
//add void InvokeSet(TThis #this, object value) if necessary
}
Then, an implementation of the interface:
public class PropertyCallAdapter<TThis, TResult> : IPropertyCallAdapter<TThis>
{
private readonly Func<TThis, TResult> _getterInvocation;
public PropertyCallAdapter(Func<TThis, TResult> getterInvocation)
{
_getterInvocation = getterInvocation;
}
public object InvokeGet(TThis #this)
{
return _getterInvocation.Invoke(#this);
}
}
The InvokeGet method looks mostly like the one Jon Skeet uses.
Now, to the "magic" part. We define a service which will build and cache an instance of the provider. It looks like this:
public class PropertyCallAdapterProvider<TThis>
{
private static readonly Dictionary<string, IPropertyCallAdapter<TThis>> _instances =
new Dictionary<string,IPropertyCallAdapter<TThis>>();
public static IPropertyCallAdapter<TThis> GetInstance(string forPropertyName)
{
IPropertyCallAdapter<TThis> instance;
if (!_instances.TryGetValue(forPropertyName, out instance))
{
var property = typeof(TThis).GetProperty(
forPropertyName,
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
MethodInfo getMethod;
Delegate getterInvocation = null;
if (property != null && (getMethod = property.GetGetMethod(true)) != null)
{
var openGetterType = typeof(Func<,>);
var concreteGetterType = openGetterType
.MakeGenericType(typeof(TThis), property.PropertyType);
getterInvocation =
Delegate.CreateDelegate(concreteGetterType, null, getMethod);
}
else
{
//throw exception or create a default getterInvocation returning null
}
var openAdapterType = typeof(PropertyCallAdapter<,>);
var concreteAdapterType = openAdapterType
.MakeGenericType(typeof(TThis), property.PropertyType);
instance = Activator
.CreateInstance(concreteAdapterType, getterInvocation)
as IPropertyCallAdapter<TThis>;
_instances.Add(forPropertyName, instance);
}
return instance;
}
}
Here, without knowing at compile time the exact TResult type, we create the adapter and cache it for subsequent usage in order to prevent heavy reflection calls in the future.
That's it. You can use it in the following way:
PropertyCallAdapterProvider<Foo>.GetInstance("Bar").InvokeGet(fooInstance)
Also, you can easily extend this for property setters if necessary.
On my machine those are the results for accessing the getter in loop ten million times, using various methods, when the adapter instance is pre-fetched from the provider before entering the loop:
141 milliseconds for direct invocation
244 milliseconds for adapter invocation
1800 milliseconds for reflection invocation
8179 milliseconds for dynamic delegate invocation
Basically, some internal check that happens in the static System.Linq.Expressions.Expression.Bind() method says "Method is not a property accessor" on my property that is clearly a property. Using Reflector, I've minimized the amount of code causing the problem, and I can't for the life of me figure out why this would happen. My only guess is that it has something to do with the fact that the property isn't on the class itself, but I would think this should still work:
I've tried to make a small example with the least amount of code possible. The code below should run in its entirety.
using System;
using System.Reflection;
public class Base
{
public virtual int Id { get; set; }
}
// As you can see, SubClass does not override the Id property of Base.
public class SubClass : Base { }
class Program
{
static void Main(string[] args)
{
// Getting the property directly from the type.
PropertyInfo propertyInfo = typeof(SubClass).GetProperty("Id");
MethodInfo setMethod = propertyInfo.GetSetMethod();
/* Code from here on out is from the System.Linq.Expressions.Bind() method (the one
that accepts a MethodInfo argument). This method causes GetProperty to be called
and retrieve what should be the same PropertyInfo. It fails here, saying something
along the lines of "Method is not a property accessor." which doesn't make sense. */
PropertyInfo propertyInfo2 = GetProperty(setMethod);
}
private static PropertyInfo GetProperty(MethodInfo mi)
{
// Not sure if it matters, but declaringType here is "Base".
Type declaringType = mi.DeclaringType;
BindingFlags bindingAttr = BindingFlags.NonPublic | BindingFlags.Public;
bindingAttr |= mi.IsStatic ? BindingFlags.Static : BindingFlags.Instance;
foreach (PropertyInfo info in declaringType.GetProperties(bindingAttr))
{
// For the "Id" property, info.CanRead is true, but CheckMethod is false.
if (info.CanRead && CheckMethod(mi, info.GetGetMethod(true)))
return info;
// For the "Id" property, info.CanWrite is true, but CheckMethod is false.
if (info.CanWrite && CheckMethod(mi, info.GetSetMethod(true)))
return info;
}
// This gets thrown after passing by the "Id" property that is the one I'm looking for.
throw new Exception("Method is not a property accessor");
}
private static bool CheckMethod(MethodInfo method, MethodInfo propertyMethod)
{
// These are not equal, so it goes to the next check. In the debugger, they appear identical when I look through the object tree.
if (method == propertyMethod)
return true;
Type declaringType = method.DeclaringType;
return ((declaringType.IsInterface && (method.Name == propertyMethod.Name)) && (declaringType.GetMethod(method.Name) == propertyMethod));
}
}
If anyone could help I would greatly appreciate it! I'm very much lost at this point.
Edit - If you substitute typeof(SubClass) with typeof(Base), it works, so it's something related to that relationship. I guess I could cut the issue off at the root by making an extension method like typeof(SubClass).GetPropertyFromActualClass("Id") but I'm not sure how to perform that check.
The property and method infos of Base and SubClass are indeed not equal, even if SubClass has no own implementation, as can be seen here:
var subPropertyInfo = typeof(SubClass).GetProperty("Id");
var subPropertyInfoSetter = subPropertyInfo.GetSetMethod();
var basePropertyInfo = typeof(Base).GetProperty("Id");
var basePropertyInfoSetter = basePropertyInfo.GetSetMethod();
Console.WriteLine(subPropertyInfo == basePropertyInfo); // false
Console.WriteLine(subPropertyInfoSetter == basePropertyInfoSetter); // false
If you use mi.ReflectedType instead of mi.DeclaringType, the check succeeds:
var type = subPropertyInfoSetter.ReflectedType;
Console.WriteLine(type.GetProperty("Id").GetSetMethod()
== subPropertyInfoSetter); // true