Sorry if the title is misleading, you can correct if you have an idea what I'm trying to say.
I have a function which takes in an IEnumberable. The IEnumerable is type annonymous.
My Function is below
public void AddToCollection_Short(IEnumerable query)
{
List<object> list = new List<object>();
foreach (var item in query)
{
var obj = new object();
var date = item.Date.ToShortDateString();
obj = new { date, item.Id, item.Subject };
list.Add(obj);
}
AllQueries = list;
OnPropertyChanged("AllQueries");
}
It doesn't recognize the suffix such as .Id, .Date, .Subject. May I ask what approach I should take to fix this. Is there something like IEnumerable<Datetime Date, int Id, string Subject> query
If you know the type, you can cast your objects
foreach (var item in query.Cast<YourType>())
If you don't know then you can use dynamic feature.And you can access your properties without a compile time error but if you try to access a property or a method which is not exist you will get a RuntimeBinderException in runtime.
foreach (dynamic item in query)
{
...
}
You could use (in C# 4.0 and higher) the dynamic keyword or update the signature to AddToCollection_Short.
public void AddToCollection_Short(IEnumerable query)
{
List<object> list = new List<object>();
foreach (dynamic item in query)
{
var obj = new object();
var date = item.Date.ToShortDateString();
obj = new { date, item.Id, item.Subject };
list.Add(obj);
}
AllQueries = list;
OnPropertyChanged("AllQueries");
}
You should be able to specify a type parameter to your method.
public void AddToCollection_Short<T>(IEnumerable<T> query) where T : IAmCommonInterface
{
List<object> list = new List<object>();
foreach (T item in query)
{
var obj = new object();
var date = item.Date.ToShortDateString();
obj = new { date, item.Id, item.Subject };
list.Add(obj);
}
AllQueries = list;
OnPropertyChanged("AllQueries");
}
and your common interface for your type paramater would have all the properties that you want on it.
The advantage to this is the compiler will tell you when you try to use this on an Enumerable that doesn't have those properties.
Related
public static IReadOnlyCollection<int> FillData(this string[] ids, IReadonlyCollection<int> list)
{
var dataList = list?.ToList() ?? new List<int>();
foreach (var id in ids)
{
dataList.Add(int.Parse(id));
}
return datalist.AsReadOnly();
}
How to create Generic method in order to receive int and long for IReadOnlyCollection param and return the value based on requested type?
Something like that should work
public static IReadOnlyCollection<T> FillData<T>(this string[] ids, IReadOnlyCollection<T> list)
{
var dataList = list?.ToList() ?? new List<T>();
foreach (var id in ids)
{
dataList.Add((T)Convert.ChangeType(id, typeof(T)));
}
return dataList.AsReadOnly();
}
PS: But keep in mind maybe you have to consider the culture.
From the world of PHP I have decided to give C# a go. I've had a search but can't seem to find the answer of how to do the equivalent to this.
$object = new Object();
$vars = get_class_vars(get_class($object));
foreach($vars as $var)
{
doSomething($object->$var);
}
I basically have a List of an object. The object could be one of three different types and will have a set of public properties. I want to be able to get a list of the properties for the object, loop over them and then write them out to a file.
I'm thinking this has something to do with c# reflection but it's all new to me.
Any help would be greatly appreciated.
This should do it:
Type myType = myObject.GetType();
IList<PropertyInfo> props = new List<PropertyInfo>(myType.GetProperties());
foreach (PropertyInfo prop in props)
{
object propValue = prop.GetValue(myObject, null);
// Do something with propValue
}
void Test(){
var obj = new{a="aaa", b="bbb"};
var val_a = obj.GetValObjDy("a"); //="aaa"
var val_b = obj.GetValObjDy("b"); //="bbb"
}
//create in a static class
static public object GetValObjDy(this object obj, string propertyName)
{
return obj.GetType().GetProperty(propertyName).GetValue(obj, null);
}
Yes, Reflection would be the way to go. First, you would get the Type that represents the type (at runtime) of the instance in the list. You can do this by calling the GetType method on Object. Because it is on the Object class, it's callable by every object in .NET, as all types derive from Object (well, technically, not everything, but that's not important here).
Once you have the Type instance, you can call the GetProperties method to get the PropertyInfo instances which represent the run-time informationa about the properties on the Type.
Note, you can use the overloads of GetProperties to help classify which properties you retrieve.
From there, you would just write the information out to a file.
Your code above, translated, would be:
// The instance, it can be of any type.
object o = <some object>;
// Get the type.
Type type = o.GetType();
// Get all public instance properties.
// Use the override if you want to classify
// which properties to return.
foreach (PropertyInfo info in type.GetProperties())
{
// Do something with the property info.
DoSomething(info);
}
Note that if you want method information or field information, you would have to call the one of the overloads of the GetMethods or GetFields methods respectively.
Also note, it's one thing to list out the members to a file, but you shouldn't use this information to drive logic based on property sets.
Assuming you have control over the implementations of the types, you should derive from a common base class or implement a common interface and make the calls on those (you can use the as or is operator to help determine which base class/interface you are working with at runtime).
However, if you don't control these type definitions and have to drive logic based on pattern matching, then that's fine.
well, in C# it's similar.
Here's one of the simplest examples (only for public properties):
var someObject = new { .../*properties*/... };
var propertyInfos = someObject.GetType().GetProperties();
foreach (PropertyInfo pInfo in propertyInfos)
{
string propertyName = pInfo.Name; //gets the name of the property
doSomething(pInfo.GetValue(someObject,null));
}
One line solution using Linq...
var obj = new {Property1 = 1, Property2 = 2};
var property1 = obj.GetType().GetProperties().First(o => o.Name == "Property1").GetValue(obj , null);
To get specific property value from property name
public class Bike{
public string Name {get;set;}
}
Bike b = new Bike {Name = "MyBike"};
to access property value of Name from string name of property
public object GetPropertyValue(string propertyName)
{
//returns value of property Name
return this.GetType().GetProperty(propertyName).GetValue(this, null);
}
You can use GetType - GetProperties - Linq Foreach:
obj.GetType().GetProperties().ToList().ForEach(p =>{
//p is each PropertyInfo
DoSomething(p);
});
Here's something I use to transform an IEnumerable<T> into a DataTable that contains columns representing T's properties, with one row for each item in the IEnumerable:
public static DataTable ToDataTable<T>(IEnumerable<T> items)
{
var table = CreateDataTableForPropertiesOfType<T>();
PropertyInfo[] piT = typeof(T).GetProperties();
foreach (var item in items)
{
var dr = table.NewRow();
for (int property = 0; property < table.Columns.Count; property++)
{
if (piT[property].CanRead)
{
var value = piT[property].GetValue(item, null);
if (piT[property].PropertyType.IsGenericType)
{
if (value == null)
{
dr[property] = DBNull.Value;
}
else
{
dr[property] = piT[property].GetValue(item, null);
}
}
else
{
dr[property] = piT[property].GetValue(item, null);
}
}
}
table.Rows.Add(dr);
}
return table;
}
public static DataTable CreateDataTableForPropertiesOfType<T>()
{
DataTable dt = new DataTable();
PropertyInfo[] piT = typeof(T).GetProperties();
foreach (PropertyInfo pi in piT)
{
Type propertyType = null;
if (pi.PropertyType.IsGenericType)
{
propertyType = pi.PropertyType.GetGenericArguments()[0];
}
else
{
propertyType = pi.PropertyType;
}
DataColumn dc = new DataColumn(pi.Name, propertyType);
if (pi.CanRead)
{
dt.Columns.Add(dc);
}
}
return dt;
}
This is "somewhat" overcomplicated, but it's actually quite good for seeing what the outcome is, as you can give it a List<T> of, for example:
public class Car
{
string Make { get; set; }
int YearOfManufacture {get; set; }
}
And you'll be returned a DataTable with the structure:
Make (string)
YearOfManufacture (int)
With one row per item in your List<Car>
This example trims all the string properties of an object.
public static void TrimModelProperties(Type type, object obj)
{
var propertyInfoArray = type.GetProperties(
BindingFlags.Public |
BindingFlags.Instance);
foreach (var propertyInfo in propertyInfoArray)
{
var propValue = propertyInfo.GetValue(obj, null);
if (propValue == null)
continue;
if (propValue.GetType().Name == "String")
propertyInfo.SetValue(
obj,
((string)propValue).Trim(),
null);
}
}
I haven't found this to work on, say Application objects. I have however had success with
var serializer = new System.Web.Script.Serialization.JavaScriptSerializer();
string rval = serializer.Serialize(myAppObj);
You can try this:
string[] arr = ((IEnumerable)obj).Cast<object>()
.Select(x => x.ToString())
.ToArray();
Once every array implements IEnumerable interface
public Dictionary<string, string> ToDictionary(object obj)
{
Dictionary<string, string> dictionary = new Dictionary<string, string>();
Type objectType = obj.GetType();
IList<PropertyInfo> props = new List<PropertyInfo>(objectType.GetProperties());
foreach (PropertyInfo prop in props)
{
object propValue = prop.GetValue(obj, null);
dictionary.Add(prop.Name, propValue.ToString());
}
return dictionary;
}
/// get set value field in object to object new (two object field like )
public static void SetValueObjectToObject (object sourceObj , object resultObj)
{
IList<PropertyInfo> props = new List<PropertyInfo>(sourceObj.GetType().GetProperties());
foreach (PropertyInfo prop in props)
{
try
{
//get value in sourceObj
object propValue = prop.GetValue(sourceObj, null);
//set value in resultObj
PropertyInfo propResult = resultObj.GetType().GetProperty(prop.Name, BindingFlags.Public | BindingFlags.Instance);
if (propResult != null && propResult.CanWrite)
{
propResult.SetValue(resultObj, propValue, null);
}
}
catch (Exception ex)
{
// do something with Ex
}
}
}
I don't know who resolve this segment code with variance:
I have an abstract father class:
public abstract class PdfObject
{...}
And two child classes:
public class PdfText : PdfObject
{...}
public class PdfImage : PdfObject
{...}
Now, my wrong or empiric code is the next:
public IList<PdfText> GetTexts()
{
List<PdfText> result = new List<PdfText>();
List<PdfObject> list = GetList();
foreach(var item in list)
{
if(item is PdfText) result.Add(item)
}
return result;
}
public List<PdfObject> GetList()
{...}
Well, i read a lot of this theme, but don't stand how use variance in generics or use a better solution for this issue.
Please, help me and thanks.
This doesn't have much to do with variance, directly. Your problem is here:
public IList<PdfText> GetTexts()
{
List<PdfText> result = new List<PdfText>();
List<PdfObject> list = GetList();
foreach(var item in list)
{
if(item is PdfText) result.Add(item)
}
return result;
}
The static type of the item variable is PdfObject so you cannot add it to result; you need to cast it. For example
if (item is PdfText) result.Add((PdfText)item);
This is inefficient because you check the type twice: once for the is operator and once for the cast. Instead, you're supposed to do this:
public IList<PdfText> GetTexts()
{
List<PdfText> result = new List<PdfText>();
List<PdfObject> list = GetList();
foreach(var item in list)
{
var textItem = item as PdfText
if (textItem != null) result.Add(textItem)
}
return result;
}
Or, you can use linq:
var result = GetList().OfType<PdfText>().ToList();
You could do this...
public IList<PdfText> GetTexts()
{
List<PdfText> result = GetList()
.Where(x => x is PdfText)
.Select(x => (PdfText)x)
.ToList();
return result;
}
Edited: This works, but OfType is better.
You could have a better solution in this situation.
public class ClientOfPdfObject<T> where T: PdfObject
{
public List<T> GetItems()
{
List<PdfObject> list = GetList();
var result = new List<T>();
foreach (var pdfObject in list)
{
if (typeof (T) == pdfObject.GetType())
result.Add((T) pdfObject);
}
return result;
}
//Get PdfObjects somewhere (ex. Db)
private List<PdfObject> GetList()
{
var list = new List<PdfObject>
{
new PdfImage(),
new PdfImage(),
new PdfImage(),
new PdfText(),
new PdfText(),
new PdfText(),
new PdfText()
};
return list;
}
}
static void main()
{
var text = new ClientOfPdfObject<PdfText>();
//contains 4 itmes (PdfText)
var pdfTexts = text.GetItems();
var image = new ClientOfPdfObject<PdfImage>();
//contains 3 items (PdfImage)
var pdfImages = image.GetItems();
}
Tomorrow, when you add more pdf objects (ex. PdfGraph), you don't need to change anything.
I have a list of objects created using reflection, they are all the same type, however the type is unknown at compile time.
I'm trying to figure out the best way of assigning this list (also using reflection) to an object property which could be any IEnumerable.
List<object>
ArrayList
Custom : List<object>
The only approach I have is to assume the property is an ICollection then loop through the IEnumerable and add each item. (See below, where list is the IEnumerable source, key is the string name of the object property and result is the object itself)
foreach (object item in list) {
PropertyInfo prop = result.GetType().GetProperty(key);
var collection = prop.GetValue(result, null);
Type collectionType = collection.GetType();
MethodInfo add = collectionType.GetMethod("Add", BindingFlags.Public | BindingFlags.Instance);
add.Invoke(collection, new object[] { item });
}
Since you say the data is homogeous, I would suggest typing it as closely as you can; so assuming list is non-empty, list[0].GetType() will tell you the Type of all the data. At this point, you could do:
IList typedList = (IList)Activator.CreateInstance(
typeof(List<>).MakeGenericType(itemType));
...
foreach(var item in list) typedListAdd(item);
or you could use an array:
Array arr = Array.CreateInstance(itemCount, list.Count);
list.CopyTo(arr, 0);
Either of which will give you a well typed list, which tends to work much better for most purposes (data-binding, serialization, or just reflection).
If list is not actually a list, but is just IEnumerable, then you can basically still do the same thing, but simply defer the creation until the first item:
IList typedList = null;
foreach(object item in list) {
if(typedList == null) {
typedList = (IList)Activator.CreateInstance(
typeof(List<>).MakeGenericType(item.GetType()));
}
typedList.Add(item);
}
return typedList ?? new object[0];
There are a couple of ways that you can add items to an existing collection of not known type:
Check for the IList interface or check of an Add method as a fallback;
public void Add(object obj, string propertyName, IEnumerable enumerable)
{
Action<object> add;
PropertyInfo prop = obj.GetType().GetProperty(propertyName);
var property = prop.GetValue(obj, null);
var collection = property as IList;
// Check for IList
if(collection != null)
{
add = item => collection.Add(item);
}
// Try to get an Add method as fallback
else
{
var objType = obj.GetType();
var addMethod = objType.GetMethod("Add", BindingFlags.Public | BindingFlags.Instance);
// Property doesn't support Adding
if(addMethod == null) throw new InvalidOperationException("Method Add does not exist on class " + objType.Name);
add = item => addMethod.Invoke(obj, new object[] { item });
}
foreach (var item in enumerable)
{
add(item);
}
}
I would probably go with Marc's way since it's more type safe.
public class Foo
{
public Foo()
{
Bar = new List<string>();
}
public List<string> Bar { get; set; }
public string Qux { get; set; }
}
var result = new Foo();
var key = "Bar";
var list = new List<object> { "A", "B" };
Add(result, key, list);
I am calling a method that returns a List variable that contains a c# Anonymous Type objects. For example:
List<object> list = new List<object>();
foreach ( Contact c in allContacts ) {
list.Add( new {
ContactID = c.ContactID,
FullName = c.FullName
});
}
return list;
How do I reference this type properties in the code I am working on like for example
foreach ( object o in list ) {
Console.WriteLine( o.ContactID );
}
I know that my sample is not possible, I have only wrote that way to say that I need to identify each property of the anonymous type exactly.
Thanks!
Solution:
Not just one of the answer is correct and/or suggest a working solution. I have ended up to using Option 3 of Greg answer. And I learned something very interesting regarding the dynamic in .NET 4.0!
You can't return a list of an anonymous type, it will have to be a list of object. Thus you will lose the type information.
Option 1
Don't use an anonymous type. If you are trying to use an anonymous type in more than one method, then create a real class.
Option 2
Don't downcast your anonymous type to object. (must be in one method)
var list = allContacts
.Select(c => new { c.ContactID, c.FullName })
.ToList();
foreach (var o in list) {
Console.WriteLine(o.ContactID);
}
Option 3
Use the dynamic keyword. (.NET 4 required)
foreach (dynamic o in list) {
Console.WriteLine(o.ContactID);
}
Option 4
Use some dirty reflection.
foreach ( var o in list ) {
Console.WriteLine( o.ContactID );
}
this will work only if list is IEnumerable<anonymous type>, like this:
var list = allContacts.Select(c => new {
ContactID = c.ContactID,
FullName = c.FullName
});
}
but you can't return anonymous types, because you must define return type (you can't return var) and anonymous types can't have names. you should create non-anonymous type if you with to pass it. Actually anonymous types should not be used too much, except for inside of queries.
If you have a method like this:
List<object> GetContactInfo() {
List<object> list = new List<object>();
foreach ( Contact c in allContacts ) {
list.Add( new {
ContactID = c.ContactID,
FullName = c.FullName
});
}
return list;
}
You shouldn't really do this, but there's a very ugly and not future-proof technique that you can use:
static T CastByExample<T>(object target, T example) {
return (T)target;
}
// .....
var example = new { ContactID = 0, FullName = "" };
foreach (var o in GetContactInfo()) {
var c = CastByExample(o, example);
Console.WriteLine(c.ContactID);
}
It relies on the fact (which can change!) that the compiler reuses anonymous types for types that have the same "shape" (properties names and types). Since your "example" matches the "shape" of the type in the method, the same type is reused.
Dynamic variables in C# 4 are the best way to solve this though.
You cannot do this with anonymous types. Just create a Contact class/struct and use that.
List<object> list = new List<object>();
foreach ( Contact c in allContacts ) {
list.Add( c );
}
Then you can do this:
foreach ( var o in list ) {
Console.WriteLine( o.ContactID );
}
...or this:
foreach ( object o in list ) {
Console.WriteLine( ((Contact)o).ContactID ); //Gives intellisense
}
Of course you should in that case just do create a Contact list instead of an object list:
List<Contact> list = new List<Contact>();
foreach ( Contact c in allContacts ) {
list.Add( c );
}
EDIT: Missed essential part of the question. Now fixed.
EDIT: Changed answer yet again. See above.
replacing object with var in for each construct may work
I know I'm late to the party but I researching somthing else and found this article which answers your question.
It is possible to cast the list of objects back into the anonymous type.
public static void Main()
{
foreach (object item in GetList())
{
var x = Cast(item, new { ContactID = 0, FullName = "" });
Console.WriteLine(x.ContactID + " " + x.FullName);
}
}
public static IEnumerable<object> GetList()
{
yield return new { ContactID = 4, FullName = "Jack Smith" };
yield return new { ContactID = 5, FullName = "John Doe" };
}
public static T Cast<T>(object obj, T type)
{
return (T)obj;
}
list back
public static void Main()
{
foreach (object item in GetList())
{
var x = Cast(item, new { ContactID = 0, FullName = "" });
Console.WriteLine(x.ContactID + " " + x.FullName);
}
}
public static IEnumerable<object> GetList()
{
yield return new { ContactID = 4, FullName = "Jack Smith" };
yield return new { ContactID = 5, FullName = "John Doe" };
}
public static T Cast<T>(object obj, T type)
{
return (T)obj;
}
i would use
allContacts
.Select(c => new { c.ContactID, c.FullName })
.ToList()
.ForEach(c => {
...do stuff;
});
then you dont need to declare at all.
i believe that less declaration, less semi-colon leads to less bug