How to get class elements dynamically in c# - c#

I may be missing basic knowledge here, but i ll go for it and ask it.
Lets say we have an array of strings:
ItemCode
ItemDescription
and we have a class:
public class InventoryItem
{
public string ItemCode { get; set; }
public string ItemDescription { get; set; }
}
I want to be able to reference the properties of an InventoryItem dynamically based on the values of the array.
I need to loop through the array and get the value of the property of the class by the current string member of the array.
How can i do it?

You use reflection:
foreach (var name in propertyNames)
{
// Or instance.GetType()
var property = typeof(InventoryItem).GetProperty(name);
Console.WriteLine("{0}: {1}", name, property.GetValue(instance, null));
}
See:
Type.GetProperty
Type.GetProperties (to find them all)
PropertyInfo.GetValue

Jon Skeet's answer is absolutely correct (does he have any other kind?) and works well if you'd need to dynamically access say 1000 InventoryItem objects. But if you need to dynamically access more objects, say 10 million, reflection starts to be painfully slow. I have a little helper class I made a while ago that can easily access a property about 26 times faster than reflection (at least on my computer) by creating and compiling a dynamic method to access the property. It's nowhere near as fast as accessing it statically, but since you need to access it dynamically that's not even a consideration. Here's how you use it:
var accessor = new DynamicPropertyAccessor(typeof(InventoryItem).GetProperty("ItemCode"));
foreach (var inventoryItem in warehouse13)
{
Console.WriteLine("{0}: {1}", accessor.Name, accessor[inventoryItem]);
}
You can also use it to set a value with: accessor[item] = "newValue". And you can have a collection of accessors if you need to access several properties dynamically. The performance gain will be substantial when you create a DynamicPropertyAccessor once per property and reuse to access many objects (or the same object many times).
I've posted the DynamicPropertyAccessor class here: https://gist.github.com/3059427

Related

Is it possible to get the Collection using reflection if i have the member of collection?

I have a sample Entity Student as below.
public class Student
{
private string _name;
public string Name
{
get
{
return _name;
}
set
{
_name = value;
}
}
private int _credits;
public int Credits
{
get
{
return _credits;
}
set
{
_credits = value;
}
}
}
I have another Class which is descendent of System.Collections.ObjectModel.Collection as below.
public class StudentCollection : System.Collections.ObjectModel.Collection<Student>
{
//SomeCollection level validations.
}
Now I am creating the student Collection Like StudentCollection c1 = new StudentCollection();.
The question is If I have a student object which is the member of c1 collection then is it possible to get the complete collection to which the object belongs to Using Reflection?
If its not possible using reflection then is there some other way out through which the above is possible.
I think you mean, given an instance (e.g. Student student), Can I get the collection that the instance belongs to.
If so, the answer is no, not using just the student.
If you have multiple collections (e.g. List<StudentCollection> studentCollections) then you could search through them all to find the list that contains the instance.
var collection = studentCollections.Where(collection => collection.Contains(student)).SingleOrDefault();
collection will then be either the collection that contains the student or null if there was no match.
The performance could be pretty awful if the collections get large though. In that case you would want to look into some sort of indexing, possibly using Dictionary.
Yes, but it is probably not what you want.
If you have the "item" you could iterate through all objects in scope, and if the object is a collection, check if the collection contains the item using Collection.Contains(item). Note that there could be multiple collections holding the same item.
This will be a very costly operation and pretty complex to implement, so most likely not appropriate for your purpose, unless you are making some kind of debugging tool or similar.
If you have a limited number of "candidate" collections, you can check if any of them contains the item by calling Collection.Contains(item).

What is the difference between an Indexer and a List in c#? [duplicate]

I'd like to use indexers more, but I'm not sure when to use them. All I've found online are examples that use classes like MyClass and IndexerClass.
What about in a school system where there are Students and Teachers, and each Teacher has a list of Students that they're in charge of - any need for indexers in that scenario? For simplicity's sake: each Student can only belong to one Teacher.
Indexer is a highly specialized property which allows instances of a class (or struct) to be indexed just like an array (properties can be static but indexers cannot).
Why to use indexers:
instead of a new data structure, the class itself is a data structure.
simplified syntax - syntactic sugar
When to use:
if your class needs list(/array) of its instances (example 1)
if your class represents list(/array) of values directly related to your class (example 2)
Example 1:
public class Person{
public string Name{get; set;}
private Person[] _backingStore;
public Person this[int index]
{
get{
return _backingStore[index];
}
set{
_backingStore[index] = value;
}
}
}
Person p = new Person();
p[0] = new Person(){Name = "Hassan"};
p[1] = new Person(){Name = "John Skeet"};
Example 2:
class TempratureRecord{
private float[] temps = new float[10] { 56.2F, 56.7F, 56.5F, 56.9F, 58.8F, 61.3F, 56.5F, 56.9F, 58.8F, 61.3F};
public int Length{
get { return temps.Length; }
}
public float this[int index]
{
get{
return temps[index];
}
set{
temps[index] = value;
}
}
}
Heres a video i have created http://www.youtube.com/watch?v=HdtEQqu0yOY and below is a detailed explanation about the same.
Indexers helps to access contained collection with in a class using a simplified interface. It’s a syntactic sugar.
For instance lets say you have a customer class with addresses collection inside it. Now let’s say we would like to like fetch the addresses collection by “Pincode” and “PhoneNumber”. So the logical step would be that you would go and create two overloaded functions one which fetches by using “PhoneNumber” and the other by “PinCode”. You can see in the below code we have two functions defined.
Customer Customers = new Customer();
Customers.getAddress(1001);
Customers.getAddress("9090");
If you use indexer you can simplify the above code with something as shown in the below code.
Customer Customers = new Customer();
Address o = Customers[10001];
o = Customers["4320948"];
Cheers.
You typically use an indexer if the class represents a list, collection or array of objects. In your case, you could provide an indexer to provide index-based access to a teacher's students.
An indexer use in your situation would be a TeachersClass class, which would encapsulate the students (collection) and the current teacher. Although you could do the same thing by exposing the list of students, but it does show you an example.
Here is a code example:
public class TeachersClass
{
private List<Student> _students;
public TeachersClass(Teacher currentTeacher, List<Student> students)
{
CurrentTeacher = currentTeacher;
_students = students;
}
public Teacher CurrentTeacher { get; set; }
public Student this[int studentID]
{
get
{
return (from s in _students
where s.Id = studentID
select s).First();
}
}
}
Random order access
You would use an enumerator if your data is normally accessed sequentially.
An indexer on the other hand is useful for directly accessing a specific element, no specific order.
This of course assumes you know the index of the element you want. Comboboxes for example have always supported two values: the string shown to the user, and the id that belongs with it. You could use the id from a selected item in a combobox to directly access the index of your collection, instead of having to search the collection.
The nice thing about indexers in C# is that you can overload them, so you can access items through different kind of keys.
The simple answer (as stated above) is when the class represents/contains a collection of items, the indexer will return the elements of the collection.
public Student this[int index] { ..
In a more advanced case you can create a default behavior with a class and make it look a bit like a delegate, especially when the class represents a mapping, or a process. For example a class that calculates the cooling rate of a beer in the refrigerator:
Instead of typing
temperature = coorsLight.CalculateFutureTemperature(time);
you can condence this to
temperature = coorsLight[time];
if the expected behavior (and intent) of the class is to return a value.
An indexer is a means to select an element from an aggregate such as an array or collection. While I agree in part with Ian Davis, I think indexers represent something more than public API polish.
Indexers are the primary means of accessing arrays and most of the major classes representing collections in the .NET BCL implemented indexers, presumably to provide a common expernce when dealing with types that aggregate other types.
Because indexers are a standard part of the interface to many of the BCLs collection types, and because these types are heavily used, as developers learn .NET as a platform, it is reasonable to suggest that an expectation is created that collections can be accessed using some type of indexer.
If your type's interface matches the expectations that developers have already, then that type becomes easier to use because the developer doesn't have to think. This is true whether the developers in question are internal to your organization or out there in the wild.
Of course there are situations where having an indexer just doesn't make sense, and if thats the case then don't implement an indexer.
Indexers allow instances of a class or struct to be indexed just like arrays. Indexers resemble properties except that their accessors take parameters.
Indexers enable objects to be indexed in a similar manner to arrays.
// C#: INDEXER
using System;
using System.Collections;
class MyClass
{
private string []data = new string[5];
public string this [int index]
{
get
{
return data[index];
}
set
{
data[index] = value;
}
}
}
class MyClient
{
public static void Main()
{
MyClass mc = new MyClass();
mc[0] = "Rajesh";
mc[1] = "A3-126";
mc[2] = "Snehadara";
mc[3] = "Irla";
mc[4] = "Mumbai";
Console.WriteLine("{0},{1},{2},{3},{4}",mc[0],mc[1],mc[2],mc[3],mc[4]);
}
}
Code project
I remember there was this time when I had a long inside a class, and some digits of that particular long meant something (for example if the third digit was a 3 it meant that the chart had a specific type of encoding, horrible system I know but I didn't invent it)
So I did something like this to return the xth digit of the number:
protected int this[int index]
{
get
{
int tempN = Number;
if (index > 0)
{
tempN /= index * 10;
}
return tempN % 10;
}
}
It was protected because a different method used it, so it was kind of a helper. Of course a simple GetDigit(int a) would've been the same thing (and more self-explanatory) but at the time I thought it was one of the few times I thought using an indexer would make sense. Haven't used them since =(.
IMHO, Indexers are probably best if you're trying to spruce up a packaged API - it's not worth the effort for your run of the mill business object.
And if you're making some specialized collection, I'd categorize that as sprucing up your packaged API - even if you keep it all in one module.

Iterate all properties of an aggregate class and instantiate?

There's all kinds of really awesome info on how to iterate through all of the properties of a class. What I want to do, however, is iterate through them and instantiate each property as new in the constructor... The class is an aggregate class representing a collection of entity framework model objects/classes. I could instantiate each in turn but that is going to be huge and a problem for maintenance when I decide to add another table to the database...
public class ClsAggModel {
public ClsAggModel() {
foreach (PropertyInfo props in this.GetType().GetProperties()) {
props.SetValue = new props.GetType(); //problem here!
}
}
public clsItem1 pProp1{ get; set; }
public clsItem2 pProp2{ get; set; }
//...and so on
The problem is that the compiler doesn't seem to know what props is at this point:
The type or namespace name 'props' could not be found (are you missing
a using directive or an assembly reference?)
which seems kind of strange since I just i stantiated it in the loop signature. I could fill out each property and do the private variable and all that jazz but what good is reflection if you can't abuse it?
Any tips?
You can not create instance on base of .GetType() in this manner.
This will not work:
new props.GetType();
You should try using:
Activator.CreateInstance(props.GetType());
Based on already provided solutions your code should look like this:
public class ClsAggModel {
public ClsAggModel() {
foreach (PropertyInfo prop in this.GetType().GetProperties()) {
var newValue = Activator.CreateInstance(prop.GetType());
prop.SetValue(this, newValue);
}
}
public clsItem1 pProp1{ get; set; }
public clsItem2 pProp2{ get; set; }
Keep in mind that all properties types must allow dynamic creation, by providing a default constructor (it is automatically there, if other constructor is not defined).
Assuming you want to call a default created type use the activator like this
props.SetValue(this, Activator.CreateInstance(props.GetType()));
Note, this will still fail if there is no default constructor. Because you are using reflection your compiler can no longer check for this.
Note 2: Be vary carefully with abusing reflection. it's a sure way to shoot yourself in the foot sooner or later.
Update of course setvalue is a method, changed this

When should you use C# indexers?

I'd like to use indexers more, but I'm not sure when to use them. All I've found online are examples that use classes like MyClass and IndexerClass.
What about in a school system where there are Students and Teachers, and each Teacher has a list of Students that they're in charge of - any need for indexers in that scenario? For simplicity's sake: each Student can only belong to one Teacher.
Indexer is a highly specialized property which allows instances of a class (or struct) to be indexed just like an array (properties can be static but indexers cannot).
Why to use indexers:
instead of a new data structure, the class itself is a data structure.
simplified syntax - syntactic sugar
When to use:
if your class needs list(/array) of its instances (example 1)
if your class represents list(/array) of values directly related to your class (example 2)
Example 1:
public class Person{
public string Name{get; set;}
private Person[] _backingStore;
public Person this[int index]
{
get{
return _backingStore[index];
}
set{
_backingStore[index] = value;
}
}
}
Person p = new Person();
p[0] = new Person(){Name = "Hassan"};
p[1] = new Person(){Name = "John Skeet"};
Example 2:
class TempratureRecord{
private float[] temps = new float[10] { 56.2F, 56.7F, 56.5F, 56.9F, 58.8F, 61.3F, 56.5F, 56.9F, 58.8F, 61.3F};
public int Length{
get { return temps.Length; }
}
public float this[int index]
{
get{
return temps[index];
}
set{
temps[index] = value;
}
}
}
Heres a video i have created http://www.youtube.com/watch?v=HdtEQqu0yOY and below is a detailed explanation about the same.
Indexers helps to access contained collection with in a class using a simplified interface. It’s a syntactic sugar.
For instance lets say you have a customer class with addresses collection inside it. Now let’s say we would like to like fetch the addresses collection by “Pincode” and “PhoneNumber”. So the logical step would be that you would go and create two overloaded functions one which fetches by using “PhoneNumber” and the other by “PinCode”. You can see in the below code we have two functions defined.
Customer Customers = new Customer();
Customers.getAddress(1001);
Customers.getAddress("9090");
If you use indexer you can simplify the above code with something as shown in the below code.
Customer Customers = new Customer();
Address o = Customers[10001];
o = Customers["4320948"];
Cheers.
You typically use an indexer if the class represents a list, collection or array of objects. In your case, you could provide an indexer to provide index-based access to a teacher's students.
An indexer use in your situation would be a TeachersClass class, which would encapsulate the students (collection) and the current teacher. Although you could do the same thing by exposing the list of students, but it does show you an example.
Here is a code example:
public class TeachersClass
{
private List<Student> _students;
public TeachersClass(Teacher currentTeacher, List<Student> students)
{
CurrentTeacher = currentTeacher;
_students = students;
}
public Teacher CurrentTeacher { get; set; }
public Student this[int studentID]
{
get
{
return (from s in _students
where s.Id = studentID
select s).First();
}
}
}
Random order access
You would use an enumerator if your data is normally accessed sequentially.
An indexer on the other hand is useful for directly accessing a specific element, no specific order.
This of course assumes you know the index of the element you want. Comboboxes for example have always supported two values: the string shown to the user, and the id that belongs with it. You could use the id from a selected item in a combobox to directly access the index of your collection, instead of having to search the collection.
The nice thing about indexers in C# is that you can overload them, so you can access items through different kind of keys.
The simple answer (as stated above) is when the class represents/contains a collection of items, the indexer will return the elements of the collection.
public Student this[int index] { ..
In a more advanced case you can create a default behavior with a class and make it look a bit like a delegate, especially when the class represents a mapping, or a process. For example a class that calculates the cooling rate of a beer in the refrigerator:
Instead of typing
temperature = coorsLight.CalculateFutureTemperature(time);
you can condence this to
temperature = coorsLight[time];
if the expected behavior (and intent) of the class is to return a value.
An indexer is a means to select an element from an aggregate such as an array or collection. While I agree in part with Ian Davis, I think indexers represent something more than public API polish.
Indexers are the primary means of accessing arrays and most of the major classes representing collections in the .NET BCL implemented indexers, presumably to provide a common expernce when dealing with types that aggregate other types.
Because indexers are a standard part of the interface to many of the BCLs collection types, and because these types are heavily used, as developers learn .NET as a platform, it is reasonable to suggest that an expectation is created that collections can be accessed using some type of indexer.
If your type's interface matches the expectations that developers have already, then that type becomes easier to use because the developer doesn't have to think. This is true whether the developers in question are internal to your organization or out there in the wild.
Of course there are situations where having an indexer just doesn't make sense, and if thats the case then don't implement an indexer.
Indexers allow instances of a class or struct to be indexed just like arrays. Indexers resemble properties except that their accessors take parameters.
Indexers enable objects to be indexed in a similar manner to arrays.
// C#: INDEXER
using System;
using System.Collections;
class MyClass
{
private string []data = new string[5];
public string this [int index]
{
get
{
return data[index];
}
set
{
data[index] = value;
}
}
}
class MyClient
{
public static void Main()
{
MyClass mc = new MyClass();
mc[0] = "Rajesh";
mc[1] = "A3-126";
mc[2] = "Snehadara";
mc[3] = "Irla";
mc[4] = "Mumbai";
Console.WriteLine("{0},{1},{2},{3},{4}",mc[0],mc[1],mc[2],mc[3],mc[4]);
}
}
Code project
I remember there was this time when I had a long inside a class, and some digits of that particular long meant something (for example if the third digit was a 3 it meant that the chart had a specific type of encoding, horrible system I know but I didn't invent it)
So I did something like this to return the xth digit of the number:
protected int this[int index]
{
get
{
int tempN = Number;
if (index > 0)
{
tempN /= index * 10;
}
return tempN % 10;
}
}
It was protected because a different method used it, so it was kind of a helper. Of course a simple GetDigit(int a) would've been the same thing (and more self-explanatory) but at the time I thought it was one of the few times I thought using an indexer would make sense. Haven't used them since =(.
IMHO, Indexers are probably best if you're trying to spruce up a packaged API - it's not worth the effort for your run of the mill business object.
And if you're making some specialized collection, I'd categorize that as sprucing up your packaged API - even if you keep it all in one module.

Getting a member via string in C#?

My question stems from MVC's SelectList (and previous generations). Basically the class takes in an IEnumerable and uses the members you define as strings.
How does it interface with the object (casting, reflection?)
(probably redundant) How does it lookup the members as a string.
This is one facet of C# that I have been interested in but could never find examples of :(
EDIT:
I ended up using DataBinder.Eval() from System.Web.UI
It still has the overhead of reflection but makes things easier by allowing you to pass the object and a string containing the hierarchy of the member you want. Right now that doesn't really mean much, but this project was designed to take in Linq data, so not having to worry about it down the road makes my life a tad easier.
Thanks everyone for the help.
While I don't know about its implementation for sure, I'd expect it to use reflection.
Basically you call Type.GetProperty or Type.GetMethod to get the relevant member, then ask it for the value of that property for a specific instance (or call the method, etc). Alternatively there's Type.GetMembers, Type.GetMember etc.
If you want to be able to use "Person.Mother.Name" or similar "paths" you have to do that parsing yourself though, as far as I'm aware. (There may be bits of the framework to do it for you, but they're not in the reflection API.)
Here's a short but complete example:
using System;
using System.Reflection;
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
class Test
{
static void Main()
{
Person jon = new Person { Name = "Jon", Age = 33 };
ShowProperty(jon, "Name");
ShowProperty(jon, "Age");
}
static void ShowProperty(object target, string propertyName)
{
// We don't need no stinkin' error handling or validity
// checking (but you do if you want production code)
PropertyInfo property = target.GetType().GetProperty(propertyName);
object value = property.GetValue(target, null);
Console.WriteLine(value);
}
}
Yes, via reflection. Take a look at the Type class and associated methods. A good place to start might be here.
You can always look at MVC's source for examples too.

Categories

Resources