Using GetProperties() with BindingFlags.DeclaredOnly in .NET Reflection
If you specify any BindingFlags
, then you need to specify explicitly what properties you want to get. For example:
sometype.GetProperties (BindingFlags.DeclaredOnly |
BindingFlags.Public |
BindingFlags.Instance);
GetProperties for inherited/child class with appropriate BindingFlags does not return expected properties
public readonly Guid Id
is a field, not a property. Use the GetField
method instead:
typeof(ChildClass).GetField("Id", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
You can check to see if it is readonly
by looking at the IsInitOnly
property of the FieldInfo
class.
var result = typeof(ChildClass).GetField("Id", BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
Assert.IsTrue(result.IsInitOnly);
Get by reflection properties of class ,but not from inherited class
You should add BindingFlags.DeclaredOnly to your flags, i.e:
typeof(Child).GetProperties(System.Reflection.BindingFlags.Public
| System.Reflection.BindingFlags.Instance
| System.Reflection.BindingFlags.DeclaredOnly)
Method GetProperties with BindingFlags.Public doesn't return anything
From the documentation of the GetProperties
method:
You must specify either BindingFlags.Instance or
BindingFlags.Static in order to get a
return.
BindingFlags - get all of them (maximum members)
You should try this:
//All actual properties:
obj.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
//or
obj.GetType().GetProperties((BindingFlags)60);
//All binding flags (if really needed):
obj.GetType().GetProperties((BindingFlags)(-1));
As you can see, it's not the same. The reason is that the BindingFlags "filters" result both explicitly and implicitly (inverted if so). That said, if you want maximum members you should pass some basic inclusive "request" BindingFlags like Public and Instance and avoid exclusive "postfilter" BindingFlags like DeclaredOnly (excludes inherited members).
Explanation:
It's binding flags, so you most likely need none of them. I guess you think of:
GetMembers(); //Simple way described in MSDN but just syntactically equivalent
BUT! Unfortunately, parameterless version returns only public members for some reason. Then, assuming you need to pass binding flags anyway (in variable, etc.), you'll probably want:
GetMembers((BindingFlags)0); //but it's like passing BindingFlags.Default
Not so obvious, but 0 means "Nothing" (which is BindingFlags.Default), not zero BindingFlags. Then what? Maybe:
GetMembers((BindingFlags)(-1));
Then you suddenly got all the BindingFlags! But not all the members (probably none at all), because they were bound.
Apparently, BindingFlags works like switchable filters: if not specified, it's vice versa (e.g. corresponding members are discarded from the end result). So finally, you need to pass most generic of them. This will be enough for most purposes:
GetMembers(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
//or
GetMembers((BindingFlags)60); //just a sum of int representations of these flags
Why -1 returns all the flags?
You need to use
-1
because its binary representation is...11111111
(for example -2 is...11111110
etc.), which means that all of its bits are "true". This is the same like using bitwise OR (Bitwise operations) with everyBindingFlags
constant. You can see it for yourself by using:
Console.WriteLine(Convert.ToString(-1, 2)); //-1 is the converted value(can be variable); 2 means converting to binary
After this you only need to convert the resulted value to
BindingFlags
asGetMembers
-like methods accept only this type.
How do I ignore all hidden properties of class being inherited using reflection?
You could use a LINQ query to filter out the hidden properties.
var allProps = typeof(Class2).GetProperties(
BindingFlags.Instance | BindingFlags.Public
);
var thePropsYouWant =
from p in allProps
group p by p.Name into g
select g.OrderByDescending(t => t.DeclaringType == typeof(Class2)).First();
See it running here: https://dotnetfiddle.net/V5sGIs
Reflection GetProperties on different custom classes and collections
I believe you are approaching your problem in the wrong way. Instead of reinventing the wheel by creating a custom MediaTypeFormatter
you should just use the correct models for your objects and let the serializer do the rest.
An example would be to use extension methods for your purpose:
public static class JsonExtensions
{
public static object CreateModels<T>(this IEnumerable<T> models, string modelName = null)
{
modelName = modelName ?? typeof(T).Name+"Collection";
return new Dictionary<string, object>()
{
{ modelName, models.Select(m => CreateModel(m)) }
};
}
public static IDictionary<string, object> CreateModel<T>(this T model, string modelName = null)
{
modelName = modelName ?? typeof(T).Name;
return new Dictionary<string, object>()
{
{ modelName, GetProperties(model) }
};
}
private static IDictionary<string, object> GetProperties<T>(T obj)
{
var props = typeof(T).GetProperties();
return props.ToDictionary(p => p.Name, p => (object)new { type = p.PropertyType.ToString(), value = p.GetValue(obj, null).ToString() });
}
}
Assuming you are using Json.NET in your project, this is how they are used:
JsonConvert.SerializeObject(new MyPerson { FirstName = "Bob", DateOfBirth = Convert.ToDateTime("1979-03-01") }.CreateModel());
Outputs (pretty printed):
{
"MyPerson": {
"FirstName": {
"type": "System.String",
"value": "Bob"
},
"DateOfBirth": {
"type": "System.DateTime",
"value": "3\/1\/1979 12:00:00 AM"
}
}
}
While:
JsonConvert.SerializeObject(new List<Foo>() {
new Foo() { Param1 = "aaa", Param2 = "bbb" },
new Foo() { Param1 = "ccc", Param2 = "ddd" }
}.CreateModels());
Outputs:
{
"FooCollection": [
{
"Foo": {
"Param1": {
"type": "System.String",
"value": "aaa"
},
"Param2": {
"type": "System.String",
"value": "bbb"
}
}
},
{
"Foo": {
"Param1": {
"type": "System.String",
"value": "ccc"
},
"Param2": {
"type": "System.String",
"value": "ddd"
}
}
}
]
}
.NET Fiddle Demo HERE
Note
I see in your examples you are using string
and not System.String
as type name for the properties. Is not easy to use the aliased type names instead of the CLR true names, but if it is really necessary you may look at this answer for a way to obtain that.
Type.GetProperties returning nothing
This code works perfectly fine for me:
namespace MyNameSpace
{
public class MyClass
{
public MyClass(Type optionsClassType)
{
//A PropertyInfo[0] is returned here
var test1 = optionsClassType.GetProperties();
//Even using typeof
var test2 = typeof(MyClassOptions).GetProperties();
//Or BindingFlags
var test3 = typeof(MyClassOptions).GetProperties
(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance);
}
}
public class MyClassOptions
{
public int MyProperty { get; set; }
}
}
Added BindingFlags.Instance
in code. For further information, have a look at this post.
Then call this from outside:
var options = new MyClassOptions();
options.MyProperty = 1234;
var t = options.GetType();
var c = new MyNameSpace.MyClass(t);
NOTE: Be careful with assembly linker
If you're building with linker enabled you may need to use the class somewhere, so it will not be ripped off at compile time. Sometimes, only instantiating the class in your code is not enough, the linker may detect that the instance is never used and will remove it anyway.
Reflection on Properties for highest level one
Try using the DeclaredOnly
binding flag in your GetProperties
call. This should limit the properties returned to the inheritance (class) level specified.
Related Topics
Twoway-Bind View's Dependencyproperty to Viewmodel's Property
Is There a Standard C++ Equivalent of Ienumerable<T> in C#
Insert Text into the Textbox of Another Application
Pinvokestackimbalance C# Call to Unmanaged C++ Function
Mailmessage C# - How to Make It HTML and Add Images etc
C#: Referencing or Using .So Files in .Net Core on Linux
Read JavaScript Variable from Web Browser Control
C# Linq Where Clause as a Variable
Application Can't Scaffold Items
Interop.Word Documents.Open Is Null
Entity Framework 4.1 Inverseproperty Attribute and Foreignkey
Is There Pointer in C# Like C++? Is It Safe
Show Data in ASP.NET HTML Table