Dynamically parsing through nested classes for values and attributes - c#

I have several models that includes nested classes and lists. Many of the class members have attributes that I also have to read in.
I'm looking for a dynamic way (possibly through Linq or Reflection) to retrieve the values and attributes of all generic objects within the specified model.
Any suggestions are welcome.
Edit:
Using the ObjectManager as per x0r's suggestion, I can see all of the data. The remaining part of this issue requires member annotation. Is there some way to copy over the PropertyInfo of each class member?
ObjectWalker objectWalker = new ObjectWalker(objectToValidate);
foreach (Object o in objectWalker)
{
if (isGeneric(o.GetType()))
{
PropertyInfo property = o.GetType().GetProperty(o); // <-- This does not work... Need to obtain annotations somehow
object[] Attributes = property.GetCustomAttributes(typeof(Attribute), true);
foreach (Attribute attribute in Attributes)
{
// Annotations processing goes here
}
}
}

Have a look at the ObjectWalker
It helps you to parse an object graph and visit all unique elements.
As you can see it stores only a stack of objects and Current returns an Object.
You could modify this so the Walker would save a class that contains all the data you need for each property (Like a propertyinfo object or a list of attributes).

Related

Is there a way to serilize specific attributes of object using annotations in modal in .net (like Groups annotation in symfony)

In Symfony, there is a way to serialize specific attributes of object using annotations in the model, this annotation is called Groups
you can see the documentation here
https://symfony.com/doc/current/components/serializer.html#component-serializer-attributes-groups-annotations
Example
class Person
{
* #Groups({"group1", "group2"})
public $firstname;
* #Groups("group2")
public $lastname;
}
so when we serilize and noralze data with
$data = $serializer->normalize($PersonObject, null, ['groups' => 'group1']);
The return will be just $firstname, but if we change group1 to group2 it gonna be $firstname and $lastname
I want to implement the same idea using annotations in .net classes and serialize specific attributes with groups,
Is there a way to do that in .net/C#?
Json.NET allows conditional property serialization via a ShouldSerialize{PropertyName}() method that you add to your class.
https://www.newtonsoft.com/json/help/html/conditionalproperties.htm#ShouldSerialize
You might be able to adapt this for your purposes. e.g. You could create a new PropertyAttribute to define the groups a property belongs too. Then, before serialization, set which matching groups you want to serialize in the object, by populating a new List GroupsToMatch property. Then in the ShouldSerialize method for each property, return true if the GroupToMatch list matches the PropertyAttribute's groups.
Example code https://dotnetfiddle.net/cKDhaw

Can I write tests for custom attributes without defining x^n classes?

I'm building a class library that includes several custom attributes that apply to properties. Then I have methods that do certain things based on the placement of the attributes.
Now I want to build some unit tests, but how to I make the tests without creating something on the order of x^(number of attributes) classes just for testing purposes? Can I leverage metadata classes or something?
Basically I'd love for there to be a way for me to apply attributes to properties at runtime (i.e. inside the "Arrange" part of my test method), but I'm pretty sure that's impossible.
Edit
This is the reflection code I'm using to test attributes, since apparently how I'm reading them may make a difference:
bool skip = false, iip = false;
string lt = null;
SerializeAsOptions sa = SerializeAsOptions.Ids;
object[] attrs = prop.GetCustomAttributes(true);
foreach (object attr in attrs)
{
Type attrType = attr.GetType();
if (typeof(JsonIgnoreAttribute).IsAssignableFrom(attrType))
{
skip = true;
continue;
}
if (typeof(IncludeInPayload).IsAssignableFrom(attrType))
iip = ((IncludeInPayload)attr).Include;
if (typeof(SerializeAs).IsAssignableFrom(attrType))
sa = ((SerializeAs)attr).How;
if (typeof(LinkTemplate).IsAssignableFrom(attrType))
lt = ((LinkTemplate)attr).LinkTemplate;
}
if (skip) continue;
I'm adding another answer, because since you now provided some code, the old one is too broad. It's now (mostly) obvious that:
you control the attribute-reading code
you are reading the code via reflection (PropertyInfo.GetCustomAttributes)
So. Since you are using Reflection, TypeDescriptors will not help. You'd need to:
either read the attrs differently so TypeDescr can be used
dynamically generate assemblies at runtime to generate classes with properties on the fly during tests
It can be very interesting/entertaining, but it can also turn into nice amount of work. But, since you control both sides of the code, none of these two is actually needed.
First, let's trim the code to significant parts:
somemethod(PropertyInfo prop)
{
// ...
object[] attrs = prop.GetCustomAttributes(true); // read ATTRs from PROP
foreach (object attr in attrs) // scan the PROP's ATTRs
{
// check attr type, do something
}
// ...
}
The core of your problem is not:
adding/removing attributes during Arrange/Teardown part
but
forcing the loop over PROP's ATTRs to see attributes that your test specifies
Looking at the problem like this, the answer is almost obvious: your loop has to abstract from the "Read attributes" part.
object[] attributeReader(PropertyInfo prop)
{
return prop.GetCustomAttributes(true);
}
somemethod(PropertyInfo prop)
{
// ...
object[] attrs = attributeReader(prop); // read ATTRs from PROP
foreach (object attr in attrs) // scan the PROP's ATTRs
{
// check attr type, do something
}
// ...
}
Now, your processing code is independent of the way the attributes are read. Sure, in the example above that way is hardcoded. But it does not have to be. Depending on how you want/like to organize your tests, you can use many ways to replace the attributeReader method with other mechanisms.
For example, just add 'virtual' to the attributeReader and use inheritance to create a class that will enable AttributeFaking:
// original class:
virtual object[] attributeReader(PropertyInfo prop)
{
return prop.GetCustomAttributes(true);
}
// derived class:
object[] AttributesOverrides {get;set;}
override object[] attributeReader(PropertyInfo prop)
{
if(prop.Name = "ShoeSize") return AttributesOverrides; // return what I say!
return base.attributeReader(prop);
}
// your test setup
var t = ... // that DERIVED object
t.AttributesOverrides = new [] { ... } ; // attributes to use
For example, use delegates/lambdas, no inheritace
// note the attributeReader is now a field, not function
Func<PropertyInfo, object[]> attributeReader = defaultAttributeReader;
static object[] defaultAttributeReader(PropertyInfo prop)
{
return prop.GetCustomAttributes(true);
}
// and your test setup
var t = ... // that ORIGNAL object
t.attributeReader = customReaderForTheTest; // change the reader on the fly
// that's the reader-function to use in THIS TEST setup
static object[] customReaderForTheTest(PropertyInfo prop)
{
if(prop.Name = "ShoeSize") return null; // crash when I say so! muhaHAHAhaa!
return prop.GetCustomAttributes(true);
}
Both of those two examples end up with one class that is enables faking the attributes in some way, but that's not the only ways to do that. You can use IoC to inject the correct attributeReader. You can do that in any way you like - you just need to abstract from reading part and leave it 'open'.
It is not possible to really apply the attribute at runtime to an existing class, but there are at least two ways you could do something similar to it - it depends on how exactly are you reading those attributes later.
The options focus on the 'really' and 'existing class' part:
1) don't do that, just fake adding them
2) apply them on a class that does not exist yet! ;)
First option is a CustomTypeDescriptor. In its implementations, you will be able to dynamically answer to any queries about Attributes for some class that uses it (-> see virtual GetAttributes method).
This leads to first way:
Create AttributableTestObject that i.e. inherits from your ClassCompatibleWithThatAttribute etc
Create something like DynamicallyAttributedClass : CustomTypeProvider that exposes a static property similar to IEnumerable<Attribute>
override the GetAttributes and return whatever was provided by that static property
on your AttributableTestObject class set a TypeDecriptorProvider attribute pointing to provider (you've got to implement it, again) that returns DynamicallyAttributedClass
Now, using that static property you can change what the GetAttributes returns, and therefore you can dynamically change the setof attributes that are visible through typedescriptor.
And here's the catch: Not all engines/observers/readers/(..) actually care about TypeDescriptors. Some simply read the metadata right away from the Reflection. Reflection will not check the typedescriptors. It will simply return an information that the AttributableTestObject class has a TypeDecriptorProvider property. But whe nusing used the ComponentModel mechanisms, the custom list of attribues will be visible.
That reminds me that the reading mechanisms simply sit at TypeDescriptor class, see its methods. There's also AddAttribute, so maybe you can even get what you want without actually implementing the stuff I said above - Try using AddAttribute and then GetAttribute on your target Type and check the results. It may "just work". But again, it will not fool the reflection.
So, there's a second, "more hardcore" approach - dynamic classes. With System.Reflection.Emit you can dynamically generate an assembly that will contain whatever IL code you wish, and then load the assembly to the current runtime.
This gives you a unique option to simply generate a new fresh class(es) at runtime, with any contents and any attributes you like. You can use inheritance, so you can inherit from any ClassCompatibleWithThatAttributes. It's not that easy to do manually, but there are some libraries that make using the IL emitter easier.
Note that the generated types will be generated at runtime. This means that at compile-time you will not have them checked, you must generate them perfectly or face some really rarely seen Exceptions. Also, note that as the types are not known at compile-time, you cannot simply new the objects. You will have to create the objects basing on their freshly-generated Type through i.e. Activator.CreateInstance(Type).
Also, even though you can generate as much new classes as you want - if you overdo it, you probably will eventually hit some CLR limit, or at leat OutOfMemory, since the generated and loaded assemblies actually occupy space. You can overcome it with AppDomains - you can create some extra AppDomains and generate and load the assemblies inside them, and then, finally, you can unload that extra domain to release all memory and also unload any assemblies that were loaded there. But, I suppose you will not generate that much types to really need that. I'm writing about it just-in-case. Dont worry until you hit the OutOfMemory or similar.

Access all properties of an unknown type

On my WinForm, I want to show each Property (as a label) and its value at run time depending on the type of the object. Something like this:
public void ShowDetails(object anyType)
{
// Generate label per property and show value of the property against a label.
}
How can I achieve this? There are more than 100 classes having different properties.
I am using C# 4.0.
You use reflection.
PropertyInfo[] properties = obj.GetType().GetProperties();
foreach (PropertyInfo property in properties)
{
object propertyValue = property.GetValue(obj, null);
}
That should be enough to get you started.
You can also get lots of other information out of the PropertyInfo such as the name of the property, the type, the accessibility, and so on. Note that it's possible (but very uncommon) to have a property without a getter, so you may want to check for that first. You also may want to only get public properties, rather than all properties. You also may want to check if the property is an indexer, as it will need a non-null value for the second parameter of GetValue. Oh, and you will also get static properties returned; you may or may not want those as well.
Use System.Reflection.PropertyInfo . You can loop through all properties (and sub-properties)
MSDN link
You can easily store the properties and their values in a dictionary
Dictionary<string,object> properties = anyType.GetType()
.GetProperties()
.ToDictionary(p=>p.Name,p=>p.GetValue(anyType,null));
I'd read up on Reflection. It will allow you to access the property names and values of class member at runtime.

Inheritance and caching in ASP.NET

I've got some class hierarchy - base class which is named "Group", which contains base information about single group, and class named "RootGroup" which inherits from "Group" and extend base class with some properties. List of groups is stored in the cache using base class: e.g. IEnumerable (some of them are ordinary groups, and some of them are root groups. The point is when the collection is being retrieved from the cache and cast back to IEnumerable type, specific information of RootGrop items are lost. Is there any way to prevent this situation except of remembering type of each cached item?
Jimmy
You can check each item as you retrieve it, and cast it to its proper type:
foreach (object item in list) {
if (item is RootGroup) {
Rootgroup rootGroup = item as RootGroup;
// do stuff with rootGroup
}
}
If you are using a generic collection, like a List<Group>, you can change the foreach like this:
foreach (Group item in list)...
If I understand your question correctly, your properties of RootGroup are not being "lost". The issue is you have a Group view of a RootGroup object. In order to access RootGroup properties, you must cast the object to a RootGroup.
A simple check:
if(groupItem is RootGroup)
{
RootGroup rootGroupItem = groupItem as RootGroup;
// Do stuff
}
Another way...
//from cache
IEnumerable<Group> groupsFromCache = GetGroupsFromCache();
IEnumerable<RootGroup> rootGroups = groupsFromCache.OfType<RootGroup>();
See http://www.thinqlinq.com/default/Using-Cast-Or-OfType-Methods.aspx
This has various niceties associated with deferred execution, but without more detail I can't really tell if that makes a difference. And like other posts noted, your information associated with the child class is not lost, you just need to put it in a form where its accessible.

How to create objects dynamically with C#?

I'm trying to create objects dynamically but I don't know how to. What I need is, I have a class for that object, and objects properties are stored in the database. Then I'll need to compare the properties of each object to get the desired result.
So I need to dynamically create objects on the fly with the properties loaded from database.
I don't think you need to create objects dynamically, just create one statically that matches your db schema with the property details, then you can compare the values of the properties across rows, or within an instance of your object.
I have been working on something similar to this. There are several things:
Include the System.Reflection namespace
Create an object dynamically using Activator
Get the object properties using the myObjectType.GetProperties() method
Here is an example of a generic object creation function using the above methods:
using System.Reflection;
public static Item CreateItem<Item>(object[] constructorArgs, object[] propertyVals)
{
//Get the object type
Type t = typeof(Item);
//Create object instance
Item myItem = (Item)Activator.CreateInstance(t, constructorArgs);
//Get and fill the properties
PropertyInfo[] pInfoArr = t.GetProperties();
for (int i = 0; i < pInfoArr.Length; ++i)
pInfo.SetValue(myItem, propertyVals[i], null); //The last argument is for indexed properties
return myItem;
}
Of course the above example assumes that the values in the property value array are arranged correctly, which is not necessarily the case, but you get the idea.
With the PropertyInfo class you can get properties, get property names, get attributes associated with the properties, etc. Powerful technology. You should be able to do what you need with the above info, but if not let me know and I will add more info.
If you have a number of objects you want to instantiate from database values it can be done something like this.
//database code goes here, results go in results
List<ClassName> l = new List<ClassName>()
foreach(Row r in results){
l.Add(new ClassName(){ClassProperty1 = r.Property1,ClassProperty2 = r.Property2});
}
Are you talking about Dictionary?
var dict=new Dictionary<string, string>();
dict.Add("property1", "val1");
dict.Add("property2", "val2");
var prop2val=dict["property2"];
Maybe Activator is what your looking for?
http://msdn.microsoft.com/en-us/library/system.activator.aspx
Check this class, compile in the realtime. But it's performance is not quite good.
http://msdn.microsoft.com/zh-cn/library/microsoft.csharp.csharpcodeprovider(VS.80).aspx
You could use reflection to dynamically build your objects:
Reflection msdn reference
I think that you want to retrieve rows from the DB and directly assign them to object given that the properties of the object are equivalent to the columns of DB table. If that what you mean then I believe you can't :)
Rob Conery did a small project called Massive that pretty much does what you're trying to accomplish. It's essentially a small ORM, in 400 lines of Dynamic C# 4.0 code.
Rob has been doing this kind of thing for quite some time with SubSonic, so you might find his approach with Massive quite interesting.
http://blog.wekeroad.com/helpy-stuff/and-i-shall-call-it-massive
Some of the code is explained here, with examples:
http://blog.wekeroad.com/microsoft/the-super-dynamic-massive-freakshow

Categories