How do I reflect over the members of dynamic object? - c#

I need to get a dictionary of properties and their values from an object declared with the dynamic keyword in .NET 4? It seems using reflection for this will not work.
Example:
dynamic s = new ExpandoObject();
s.Path = "/Home";
s.Name = "Home";
// How do I enumerate the Path and Name properties and get their values?
IDictionary<string, object> propertyValues = ???

In the case of ExpandoObject, the ExpandoObject class actually implements IDictionary<string, object> for its properties, so the solution is as trivial as casting:
IDictionary<string, object> propertyValues = (IDictionary<string, object>)s;
Note that this will not work for general dynamic objects. In these cases you will need to drop down to the DLR via IDynamicMetaObjectProvider.

There are several scenarios to consider.
First of all, you need to check the type of your object. You can simply call GetType() for this.
If the type does not implement IDynamicMetaObjectProvider, then you can use reflection same as for any other object. Something like:
var propertyInfo = test.GetType().GetProperties();
However, for IDynamicMetaObjectProvider implementations, the simple reflection doesn't work. Basically, you need to know more about this object. If it is ExpandoObject (which is one of the IDynamicMetaObjectProvider implementations), you can use the answer provided by itowlson. ExpandoObject stores its properties in a dictionary and you can simply cast your dynamic object to a dictionary.
If it's DynamicObject (another IDynamicMetaObjectProvider implementation), then you need to use whatever methods this DynamicObject exposes. DynamicObject isn't required to actually "store" its list of properties anywhere. For example, it might do something like this (I'm reusing an example from my blog post):
public class SampleObject : DynamicObject
{
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = binder.Name;
return true;
}
}
In this case, whenever you try to access a property (with any given name), the object simply returns the name of the property as a string.
dynamic obj = new SampleObject();
Console.WriteLine(obj.SampleProperty);
//Prints "SampleProperty".
So, you don't have anything to reflect over - this object doesn't have any properties, and at the same time all valid property names will work.
I'd say for IDynamicMetaObjectProvider implementations, you need to filter on known implementations where you can get a list of properties, such as ExpandoObject, and ignore (or throw an exception) for the rest.

If the IDynamicMetaObjectProvider can provide the dynamic member names, you can get them. See GetMemberNames implementation in the apache licensed PCL library Dynamitey (which can be found in nuget), it works for ExpandoObjects and DynamicObjects that implement GetDynamicMemberNames and any other IDynamicMetaObjectProvider who provides a meta object with an implementation of GetDynamicMemberNames without custom testing beyond is IDynamicMetaObjectProvider.
After getting the member names it's a little more work to get the value the right way, but Impromptu does this but it's harder to point to just the interesting bits and have it make sense. Here's the documentation and it is equal or faster than reflection, however, unlikely to be faster than a dictionary lookup for expando, but it works for any object, expando, dynamic or original - you name it.

Requires Newtonsoft Json.Net
A little late, but I came up with this. It gives you just the keys and then you can use those on the dynamic:
public List<string> GetPropertyKeysForDynamic(dynamic dynamicToGetPropertiesFor)
{
JObject attributesAsJObject = dynamicToGetPropertiesFor;
Dictionary<string, object> values = attributesAsJObject.ToObject<Dictionary<string, object>>();
List<string> toReturn = new List<string>();
foreach (string key in values.Keys)
{
toReturn.Add(key);
}
return toReturn;
}
Then you simply foreach like this:
foreach(string propertyName in GetPropertyKeysForDynamic(dynamicToGetPropertiesFor))
{
dynamic/object/string propertyValue = dynamicToGetPropertiesFor[propertyName];
// And
dynamicToGetPropertiesFor[propertyName] = "Your Value"; // Or an object value
}
Choosing to get the value as a string or some other object, or do another dynamic and use the lookup again.

Simple solution to only reflect over json objects:
using System.Collections.Generic;
using System.Text.Json;
dynamic d = new {a = 1, b = 2, c = 3};
foreach ((string k, object o) in JsonSerializer.Deserialize<Dictionary<string, object>>(JsonSerializer.Serialize(d)))
{
}

Related

Convert KeyValuePair to anonymous type in a LINQ query

I have an IEnumerable<KeyValuePair<string,string>>, from which I would like, ideally, an anonymous object which has the keys as property names and the values as property values.
I've tried various selection expressions (none of which even compiled...) and an approach using ExpandoObject (see below), but without success. Is there a good way to do this? If possible, I'd like to avoid an extra explicit iteration over the collection (i.e. do it all with a LINQ statement of some sort).
This is what I've tried so far. I hope it also clarifies what I'm trying to do:
var kvps = getProps(); // returns IEnumerable<KeyValuePair<string,string>>
dynamic o = new ExpandoObject();
foreach (var kvp in kvps)
{
o.Add(kvp);
}
This is OK at compile time, but at runtime I get a YSOD stating 'System.Dynamic.ExpandoObject' does not contain a definition for 'Add' - I guess it works at compile time because o is dynamic, so the compiler can't know if a method .Add() has been added to it since it was instantiated. The odd thing is, that on the MSDN documenation page for ExpandoObject .Add() is listed as one of several "explicitly implemented interface methods".
It is not necessary for me to get this into a dynamic object - I just need to get something that has property names and values according to the keys and values of the key-value pairs.
Update: Well, this is embarrassing. Turns out this was something of an XY-problem too.
I'm trying to render this to JSON using the built-in features of ASP.NET MVC, by simply returning Json(data) in my controller. The answers all worked very well to do what I first asked, but when I pass this object as data I still don't get what I want:
// What I get:
[
{ Key: 'firstkey', Value: 'FirstValue' },
{ Key: 'secondKey', Value: 'secondValue' }
]
// What I want:
{ firstKey: 'FirstValue', secondKey: 'secondValue' }
Apparently, an ExpandoObject with the relevant properties added didn't cut it - it was cast to a dictionary before rendering...
You need to use the ExpandoObject as an IDictionary<string, object> while populating it:
var kvps = getProps(); // returns IEnumerable<KeyValuePair<string,string>>
IDictionary<string, object> o = new ExpandoObject();
foreach (var kvp in kvps)
{
// Or use Add(kvp.Key, kvp.Value), if you want
o[kvp.Key] = kvp.Value;
}
dynamic d = o;
// Now you can use the properties
ExpandoObject explicitly implements IDictionary<string, object> - so you need to cast it to one first:
var kvps = getProps();
dynamic o = new ExpandoObject();
var dict = o as IDictionary<string, object>;
foreach (var kvp in kvps)
{
dict.Add(kvp.Key, kvp.Value);
}
Now you can use o as you would expect:
var example = o.YourKey;
I'm trying to render this to JSON using the built-in features of ASP.NET MVC, by simply returning Json(data) in my controller.
Interesting.
To do that, you serialize a dictionary, not an ExpandoObject. MVC 3's JSON serializer already does that with a dictionary. All you have to do is convert your IEnumerable<KeyValuePair<string, object>> to a dictionary:
var kvps = getProps();
var dictionary = kvps.ToDictionary(k => k.Key, v => v.Value);
return Json(dictionary, JsonRequestBehavior.AllowGet); //take out allow get if you don't need it.
No dynamics required.
I think you have to cast your expando object to IDictionary and call Add(string, object)

Converting a KeyValuePair collection in to anonymous type

Is it possible to convert a a IEnumerable<KeyValuePair<string,string>> of KeyValuePair to an anonymous type?
Dictionary<string, string> dict= new Dictionary<string, string>();
dict.add("first", "hello");
dict.add("second", "world");
var anonType = new{dict.Keys[0] = dict[0], dict.Keys[1] = dict[1]};
Console.WriteLine(anonType.first);
Console.WriteLine(anonType.second);
********************output*****************
hello
world
The reason i would like to do this is because I am retrieving an object from a webservice that represents an object that does not exist in the wsdl. The returned object only contains a KeyValuePair collection that contains the custom fields and their values. These custom fields can be named anything, so i cant really map an xml deserialization method to the final object i will be using (whose properties must be bound to a grid).
*Just because I used Dictionary<string,string> does not mean it is absolutely a dictionary, i just used it for illustration. Really its an IEnumerable<KeyValuePair<string,string>>
Ive been trying to thing of a way to do this, but am drawing a blank. This is c# .NET 4.0.
You could use the ExpandoObject, it is based on a dictionary.
I think there are a lot of ways to achieve this, but actually converting it in the same Dictionary seems a bit odd to do.
One way to accomplish this, by not actually converting everyting is the following:
public class MyDictionary<T,K> : Dictionary<string,string> // T and K is your own type
{
public override bool TryGetValue(T key, out K value)
{
string theValue = null;
// magic conversion of T to a string here
base.TryGetValue(theConvertedOfjectOfTypeT, out theValue);
// Do some magic conversion here to make it a K, instead of a string here
return theConvertedObjectOfTypeK;
}
}
ExpandoObject is the best option, which I believe is a wrapper around some XML. You could also use an XElement:
var result = new XElement("root");
result.Add(new XElement("first", "hello"));
result.Add(new XElement("second", "world"));
Console.WriteLine(result.Element("first").Value);
Console.WriteLine(result.Element("second").Value);
foreach (var element in result.Elements())
Console.WriteLine(element.Name + ": " + element.Value);
I haven't used ExpandoObject, so I'd try that first because I understand it does exactly what you want and is also something new and interesting to learn.

Compare type of IEnumerable<T>

I have dictionary that gives me back a method according to the value passed in. Defined as so:
Dictionary<Type, IXmlWriterConverter>
I have now added a new function that which has the Key/type set to IEnumerable, so far so good.
But when I execute my unit test with a List containing two DataTables but the dictionary can not find the key e.g. my type conversion differs.
Why is that so? And what would be the right attempt to solve my problem?
Edit: Sorry here is the requested code ;-)
Function that generates the testvalues:
public IEnumerable<DataTable> CreateTestDataTableList()
{
var resultDataTable = new List<DataTable>();
resultDataTable.Add(CreateTestTable("testTable1", 2));
resultDataTable.Add(CreateTestTable("testTable2", 3));
return resultDataTable;
}
Function called by the unit test:
public void Write(XmlWriter xmlWriter, object value)
{
...
converter = FindConverter(value.GetType());
}
Function checking the dictionary:
public IXmlWriterConverter FindConverter(Type type)
{
if(Converters.ContainsKey(type))
{
return Converters[type];
}
return null;
}
2.Edit:
Code that adds the values to the Dictionary:
public void Add(IXmlWriterConverter xmlWriterConverter)
{
if(Converters.ContainsKey(xmlWriterConverter.InputType))
{
Remove(xmlWriterConverter);
}
Converters.Add(xmlWriterConverter.InputType, xmlWriterConverter);
}
The InputType is a readonly (get) property of the converter. I checked the type added to the dictionary and that was registered as IEnumerable, however when I checked on the typeof when passing in my list the type was List and not IEnumerable. I was told that this happens because I pass in the values as object.
This is a really code-stinky solution to me, and it cuts down on the efficiency, but you can also iterate through the GetInterfaces() method on Type, like this:
List<DataTable> l = new List<DataTable>();
var t = l.GetType();
var ints = t.GetInterfaces();
Then you could do a lookup on the type, and, if that doesn't work do a lookup on it's interfaces.
However, this feels like a terrible hack, which usually indicates that some more design work needs to be done. Is it not possible to put the List type in the dictionary? Is there no better way of doing this lookup?
Also, a note on doing dictionary lookups: It's more efficient to use the TryGetValue method, like this:
public IXmlWriterConverter FindConverter(Type type)
{
IXmlWriterConverter converter;
if( Converters.TryGetValue(type, out converter) )
{
return converter;
}
return null;
}
When you do it this way, it only does one lookup on the dictionary, whereas if you use ContainsKey it has to do two lookups.
Its a bit of hack but the only thing that gets into my mind when looking at your code, is to add an other generic write method:
public void Write<TValue>(XmlWriter writer, TValue value) {
// ...
}
This allows to identify the right type for IEnumerable and leaves the other Write method to not break any existing code.
Probably you are trying to retrieve List type and not IEnumerable (inheritance is not going to work in this context)
Please paste the code that does the lookup if you want more details and more certain answer :)
You should also post the code of where you are retrieving the test values. But based on what you've given, are you possibly using the non-generic IEnumerable to retrieve the values instead of the generic version that you're using to generate them?
The InputType is a readonly (get)
property of the converter. I checked
the type added to the dictionary and
that was registered as IEnumerable,
however when I checked on the typeof
when passing in my list the type was
List and not IEnumerable. I was told
that this happens because I pass in
the values as object.
Like they say on MythBusters, well, there's your problem! Even though List is-a IEnumerable the Type objects that represent each are definitely not the same. In programmer jargon, typeof(List) != typeof(IEnumerable). That is why the lookup is not working.

Dynamic Object Serialization

I tried to serialize a DynamicObject class with BinaryFormatter, but:
Output file is too big, not exactly wire-friendly
Circular References not handled (stuck while serializing)
Since serializing a DynamicObject means very little by itself, here's the class I tried to serialize:
[Serializable()]
class Entity
: DynamicObject, ISerializable
{
IDictionary<string, object> values = new Dictionary<string, object>();
public Entity()
{
}
protected Entity(SerializationInfo info, StreamingContext ctx)
{
string fieldName = string.Empty;
object fieldValue = null;
foreach (var field in info)
{
fieldName = field.Name;
fieldValue = field.Value;
if (string.IsNullOrWhiteSpace(fieldName))
continue;
if (fieldValue == null)
continue;
this.values.Add(fieldName, fieldValue);
}
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
this.values.TryGetValue(binder.Name, out result);
return true;
}
public override bool TrySetMember(SetMemberBinder binder, object value)
{
this.values[binder.Name] = value;
return true;
}
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
{
foreach (var kvp in this.values)
{
info.AddValue(kvp.Key, kvp.Value);
}
}
}
(I guess I could have used an ExpandoObject, but that's another story.)
Here's a simple test program:
static void Main(string[] args)
{
BinaryFormatter binFmt = new BinaryFormatter();
dynamic obj = new Entity();
dynamic subObj = new Entity();
dynamic obj2 = null;
obj.Value = 100;
obj.Dictionary = new Dictionary<string, int>() { { "la la la", 1000 } };
subObj.Value = 200;
subObj.Name = "SubObject";
obj.Child = subObj;
using (var stream = new FileStream("test.txt", FileMode.OpenOrCreate))
{
binFmt.Serialize(stream, obj);
}
using (var stream = new FileStream("test.txt", FileMode.Open))
{
try
{
obj2 = binFmt.Deserialize(stream);
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
}
Console.ReadLine();
}
Putting some breakpoints here and there helped me have a look at obj2 contents and it looks like the original data is correctly deserialized, though with the above shortcomings if you get imaginative and move data around.
I had a look at Marc Gravell's protobuf-net, but I'm not really sure how to use it in such a context (I'm not even sure I picked up the right version from the repository, but hey).
I know it's more code than words, but I don't think I can explain the scenario any better. Please do tell if there's something I can add to make this question clearer.
Any help is much appreciated.
I'm 98% certain that this sequence will work for a dynamic object.
convert object to an Expando Object
cast expando object to be of type Dictionary
use ProtoBuf-net Serializer.Serialize / .Deserialize as per normal
convert dictionary to Expando Object
You can convert objects to a collection of name/value pairs for transfering.
That's just a small subset of what dynamic can do, but perhaps it is enough for you.
There's some custom code to handle some of the conversions above that I can show you if there's interest.
I don't have a solution for when dynamic is a placeholder to a class. For this case I'd suggest getting the type and using a switch statement to serialize / deserialize as you require. For this last case, you'd need to place a something to indicate which type of generic deserialization that you need (string / id / fully qualified type name / etc). Assumption is that you are dealing with a list of expected types.
Note: Expando implements IDictionary. An Expando is merely merely a list of key/value pairs. ie. the thing you dot into is the key, and the value is the return from whatever chain of functions implements that. There are a set of dynamic interfaces for customising the syntactic sugar experience, but most of the time you wont to look at them.
refs:
Dictionary from IDictionary using the constructor -- http://msdn.microsoft.com/en-us/library/et0ke8sz(v=vs.110).aspx
IDictionary/Dictionary to Expando -- http://theburningmonk.com/2011/05/idictionarystring-object-to-expandoobject-extension-method/
I am not sure if JSON would be acceptable in your senario, but if it is I have used Json.net (http://json.codeplex.com) to serialize a dynamic types. It works quite well, it is fast, and the output is small in size. While Json.net doesn't return dynamic objects directly, it is very easy to convert the deserialized output of Json.Net to any dynamic type. In the example below I am using ExpandoObject as my dynamic type. The code below is what I have used in the Facebook Graph Toolkit. See this link for the original source: http://facebookgraphtoolkit.codeplex.com/SourceControl/changeset/view/48442#904504
public static dynamic Convert(string s) {
object obj = Newtonsoft.Json.JsonConvert.DeserializeObject(s);
if (obj is string) {
return obj as string;
} else {
return ConvertJson((JToken)obj);
}
}
private static dynamic ConvertJson(JToken token) {
// FROM : http://blog.petegoo.com/archive/2009/10/27/using-json.net-to-eval-json-into-a-dynamic-variable-in.aspx
// Ideally in the future Json.Net will support dynamic and this can be eliminated.
if (token is JValue) {
return ((JValue)token).Value;
} else if (token is JObject) {
ExpandoObject expando = new ExpandoObject();
(from childToken in ((JToken)token) where childToken is JProperty select childToken as JProperty).ToList().ForEach(property => {
((IDictionary<string, object>)expando).Add(property.Name, ConvertJson(property.Value));
});
return expando;
} else if (token is JArray) {
List<ExpandoObject> items = new List<ExpandoObject>();
foreach (JToken arrayItem in ((JArray)token)) {
items.Add(ConvertJson(arrayItem));
}
return items;
}
throw new ArgumentException(string.Format("Unknown token type '{0}'", token.GetType()), "token");
}
First off, the size of your file depends on 2 things (if I understand how BinaryFormatter works, please correct me if I'm wrong):
The size of the actual values being serialized, and
The names used to serialize the object's values with the SerializationInfo.AddValue method, which are stored in the output file so values can be used during deserialization with the same name.
Obviously, #1 is going to cause your biggest slowdown, which can only be reduced by optimizing the objects you're trying to serialize.
Because you're using dynamic objects, the almost unnoticably small size increase caused by #2 is unavoidable. If you knew the types and names of the object's members ahead of time, you could just give each member of the object very short, sequentially-determined name ("1", "2", "3", etc.) as you iterated over the object's members, adding them via SerializationInfo.AddValue. Then, during deserialization, you could use SerializationInfo.GetValue with the same sequentially-determined name, and deserialization would work just fine, regardless of the actual names of the values being deserialized, as long as you iterated through the object's members in the same order they were added in. Granted, this might only save you an average of 4 or 5 bytes per member, but those little amounts can add up in large objects.
#Raine: (I guess I could have used an ExpandoObject, but that's another story.)
Not so; I changed your code sample to use ExpandoObject instead of your Entity class, and got a SerializationException thrown at me. ExpandoObject is not marked with a SerializableAttribute, and it doesn't have the appropriate constructors to be deserialized or serialized. However, this doesn't mean you can't use ExpandoObject if you really want to: it implements IDictionary<string, object>, which in turn implements ICollection<KeyValuePair<string, object>>. Thus, an ExpandoObject instance is a collection of KeyValuePair<string, object> instances, which are marked as serializable. So, you could serialize an ExpandoObject, but you'd have to cast it as ICollection<KeyValuePair<string, object>> and serialize each KeyValuePair<string, object> in it individually. This would pointless, though, in terms of optimizing your original code sample, because it takes just as much file space.
In summary, I really don't think there's any way you could optimize serializing a dynamic object- you have to loop through the object's members every time it's serialized, and you have no way to know the object's size beforehand (by definition of dynamic).
I don't know if SharpSerializer supports Dynamic Objects but it might be worth a try:
http://www.sharpserializer.com/en/index.html
One Suggestion for serializing dynamic object is convert them to String and then serialize, you can then deserialize back to your object, if applicable in your case.

Generic method to recive any type of object and convert the object to a List<string>

EDIT AGAIN: the solution was probably different from my original question. Thanks everyone very much your great ideas. I wish I could vote for more than one answer.
EDIT: I am populating a Jquery table plugin from datatables/.net and it requires the data (Json) to be in a certain format like this;
"sEcho": 1,
"iTotalRecords": 57,
"iTotalDisplayRecords": 57,
"aaData": [
[
"Gecko",
"Firefox 1.0",
"Win 98+ / OSX.2+",
"1.7",
"A"
],
[
"Gecko",
"Firefox 1.5",
"Win 98+ / OSX.2+",
"1.8",
"A"
],
...
]
}
I am recieving data from a service that is returning a collection of object. I would like one method which I can pass these collections into and it will return the appropriate string
thanks
END EDIT
I would like to build a method that can receive and object that we build and will return an array List each containing the value of each object passed in. For example;
I have a collection of 'Car' objects
What I would like to do is
public object[] Something<T>(_cars)
{
object[] objArray = new object[_cars.Count];
foreach(Car _car in _cars ){
IList objList = new List<string>;
objList.Add(_car.Color);
objList.Add(_car.EngineSize);
//etc etc
objArray[i] = objList;//i'll have to use a for loop to get the i counter but you get my idea
}
return objArray
}
my problem is how can I access the properties of the object without knowing what type of object it is?
thanks for any help
Update: To answer your revised question - produce a JSON result of a data structure - use the built-in JavaScriptSerializer class:
JavaScriptSerializer serializer = new JavaScriptSerializer();
string json = seriaizer.Serialize(myObjectOrArray);
Below is the previous answer.
how can I access the properties of the object without knowing what type of object it is
Using Reflection, and grabbing the properties which are strings. Note this is not necessarily a good idea. The fact that you have to use reflection to get what you want is usually a HUGE WARNING FLAG that your design is wrong.
However, in the hopes of learning something useful, here's how it could be done:
public object[] Something<T>(T[] items)
{
IList objList = new List<object>();
//get the properties on which are strings
PropertyInfo[] properties = typeof(T).GetProperties().Where(p => p.PropertyType == typeof(string));
foreach(T item in items)
{
IList stringList = new List<string>;
foreach(PropertyInfo property in properties)
{
objList.Add(property.GetValue(item, null) as string);
}
objList.Add(stringList);
}
}
return objList.ToArray();
}
A far, far better solution would be to require all the objects coming into this method to conform to some interface that requires them to provide their own string-formatted data. Or maybe take two steps back and ask for help on the underlying problem. This approach is fraught with problems. It's a rabbit hole you don't want to go down.
Use the System.Web.Script.Serialization.JavaScriptSerializer class. It was specifically provided for JSON serialization.
using System.Web.Script.Serialization;
public string ToJson(object o)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
return serializer.Serialize(o);
}
EDIT: Oops, I missed that your plugin doesn't want a true JSON representation of the objects; it just wants arrays of values. You could use reflection to iterate over the properties of the objects as others have suggested, but then you have no control over which properties end up in which columns. It is not clear from your question whether that is a problem for you.
If you need a strict mapping between properties and columns, then you will have to define that somehow in C#. To do this you could implement IEnumerable as Ed demonstrates or create a custom interface:
public interface ITableDataSource
{
IList<string> GetTableData();
}
Then implement this on any objects that might need to be data sources for the jQuery table plugin:
public class Car : ITableDataSource
{
//...class implementation details...
public IList<string> GetTableData()
{
return new List<string>()
{
this.Color,
this.EngineSize,
this.NumberOfSeats.ToString()
};
}
}
Finally, in your method that is returning the data to the jQuery plugin, use the interface to construct your response object, then pass it to my ToJson() method to serialize it:
public string DoSomething(IList<ITableDataSource> objects)
{
var result = new
{
sEcho = 1,
iTotalRecords = 1,
iTotalDisplayRecords = 1,
aaData = new List<IList<string>>()
};
foreach (ITableDataSource ds in objects)
result.aaData.Add(ds.GetTableData());
return ToJson(result);
}
While it would be relatively straightforward to use reflection to loop through all of your objects and all the properties on those objects to build that string, it's already been written.
I would highly recommend looking at the Json.NET project found here. Add this DLL to your project and converting a list of objects into a Json formatted string is as easy as:
string json = Newtonsoft.Json.JsonConvert.SerializeObject( listOfCars );
IList objList = new List<string>();
foreach ( PropertyInfo prop in _car.GetType().GetProperties() )
{
var value = prop.GetValue( _car, null );
objList.Add( value != null ? value.ToString() : null );
}
objArray[i] = objList;
The code to get the Property values of an object is
foreach (PropertyInfo info in myObject.GetType().GetProperties())
{
if (info.CanRead)
{
object o = propertyInfo.GetValue(myObject, null);
}
}
my problem is how can I access the properties of the object without knowing what type of object it is?
Well, in the general sense you can't. Generics is all about treating objects generically. However, you can impose type constraints by using a where clause. Based on the foreach loop I would say constrain your types to types that implement IEnumerable, but then you go on to use properties like "Color" and "EngineSize", which are very specific. I don't even know why you would have properties named "Color" and "EngineSize" that are strings, but that is another problem altogether...
It seems like the best approach for you would be to define an interface or an abstract base class that each of these objects inherits from. Then you can use the 'where' clause to constrain to objects of that interface/base class only So...
public object[] Something<T>( T _cars) where T : IEnumerable<MyInterface>
However, if we are going to go down this road I don't see why the method should be generic at all. It could simply take an IEnumerable<T> as an input. When we only want to use one type in a method generics is not needed.

Categories