Im trying to write a small framework for REST-API testing. Im using a lot of reflection and came to a problem I cant help myself.
Im using this line to extract a variable the user gives my as a path (string)
object o = input.GetType().GetProperty(name).propertyInfo.GetValue(input, null);
This object can be a normal type T or a List<T>.
Now if its a List and I know the type everything is simple, I can use
List<string> l = (List<string>)o; // I know its a List<string> because the user told me
To parse the object into the given array. But I dont always know the type of the objects in the list and
List<object> l = (List<object>)o; // I dont know the type and I dont care
gives me an error.
Object of type "System.Collection.GenericList[System.String]" can not
be converted to "System.Collection.GenericList[System.Object]"
Is there anything I can do to receive the list of objects? I dont want the user to specify the type because its only the last variable I want to care about. Like
The user wants to test "object1.a.b.c" I only need to know the type of c, because thats where the test runs.
TIA
You may convert it to IEnumerable<object>, but not List<object>. The reason is: a list of bananas is not a list of fruit because you can put an apple into a list of fruit, but not into a list of bananas. Since the two types allow different operations, they are not compatible.
A sequence has no "put into" operation, so it is possible to use a list of bananas as a sequence of fruit. Similarly, you can use a list of strings as a sequence of objects, but not a list of objects.
This feature is called generic covariance; for more information, do a search on C# covariance and you'll find plenty of articles explaining how it works.
Note in particular that covariance only works on reference types; you may not use a sequence of integers as a sequence of objects. Do you see why?
Alternatively, if you have an IEnumerable in hand, you can make a copy of any sequence into a list of objects with mysequence.Cast<object>().ToList(). But this is a copy, not a reference conversion.
Since your problem begins at processing dynamic objects that arrive as JSON to the server, it's quite convenient to use the JSON Processing library itself to test for certain characteristics before converting to POCOs. Using newtonsoft's JSON.Net,
var o = JObject.Parse(json);
JToken property = o["a"]["b"]["c"];
if (property != null)
{
if (property.Type == JTokenType.Array)
{
// Process property as array
}
else if (property.Type == JTokenType.Object)
{
// Process property as object
}
// Magnitude of other types
}
I do understand the need to convert to .NET types before final processing but I would highly recommend beginning with JObjects as the library is designed for this purpose and provides numerous convenience methods for many dynamic operations that C# doesn't provide natively.
JToken Type Reference
JObject Class
Related
For this code snippet below, which probably won't need an explanation to the persons who can answer my question:
protected readonly List<TEntity> Records; //Within the class declared.
protected virtual void ReadFile()
{
//So the file exists, is not null and not whitespace only
var serializer = new XmlSerializer(Records.GetType());
using (var reader = new StringReader(contents))
{
var records = (List<TEntity>)serializer.Deserialize(reader);
Records.Clear();
Records.AddRange(records);
}
}
It's about the line:
var records = (List<TEntity>)serializer.Deserialize(reader);
(1) How could I've known (deduced) that this cast was possible? I looked up that the Deserialize() methods returns the type "object". So that's can't be the hint. (Edit: I mean during coding/design time. Not compiling afterwards for trial and error. So think goal-wise: goal = store xml data into a list<>. Is it possible through a simple cast (yes) and how could I have known in advance?).
(2) How could I've / can I deduce(d) how variable "records" would end up? For example, what shouldn't make me think that only a single entry is written to the list and that single index holds all of the XML content? (as opposed to keeping a nice structure whilst writing it to the list)
The final goal of my question is to understand when such a cast is needed and especially how the actual cast makes sense. I'm wiling to put in effort in it with practice and experimentations. But I don't know how to think.
a) I"m a beginner, though learning fast i.m.o.
b) I Have read and understood implicit/explicit casting and understood that it's based on range, as opposed to data size. But those tutorials restrict to built in basic types like int, float, decimal (you name it). Now this problem domain (casting) I would like to move to a higher level.
The cast
var records = (List<TEntity>)serializer.Deserialize(reader);
works because of
new XmlSerializer(Records.GetType());
The cast from object to anything will always compile but yield a runtime exception when the types don't match.
The serializer knows about the root type from its constructor and will create a result of that type. If the XML doesn't match that, it will throw an error. You cannot deserialze a single TEntity with this, only a List<> with 0 or more elements.
You can verify it easily:
object temp = serializer.Deserialize(reader);
// print or inspect temp.GetType() here
var records = (List<TEntity>)temp;
Note that if XmlSerialzier had been designed as a generic type then the cast would not have been necessary:
var serializer = new XmlSerializerGeneric<List<TEntity>>();
var records = serializer.Deserialize(reader);
But it wasn't, it uses the older way of 'dynamic typing' through the System.Object class.
It would be much obvious if instead of this
var serializer = new XmlSerializer(Records.GetType());
you used this
var serializer = new XmlSerializer(typeof(List<TEntity>));
The rule is simple. What ever type you pass to the XmlSerializer constructor, you can safely cast the Deserialize result to that type.
The cast is needed because XmlSerializer (as well as Enum and many other framework classes) exists from a long time before the generics were added, so returning an object is the only choice it had. And it must remain this way because of backward compatibility (to not break the existing code you have written).
How could I've known (deduced) that this cast was possible?
One way is to use the debugger. Put a breakpoint on the Records.Clear(); line just after records is set. Then in either the Watch window or the Locals window, take a look at the type of the records variable. It might say something like this:
object { List<TEntity> }
records is a List<TEntity> but it's being passed as an object because the call to serializer.Deserialize(reader) returns an object. And if you didn't declare an implicit conversion from object to List<TEntity>, you have to use an explicit conversion.
I recommend against implicit conversions for all but the most obvious cases.
(1) How could I've known (deduced) that this cast was possible?
It all began here,
protected readonly List<TEntity> Records;
You don't have to deduce but you already know you are reading file contents from a file which has some XML with some sort of structure and since you are using a list you know upfront that there are going to be mulitple list items
I looked up that the Deserialize() methods returns the type
"object". So that's can't be the hint.
object class is not used directly (So basically that is a hint that you have to cast) and it must be casted to some type (in this case List<TEntity>) before it could be used.
(2) How could I've / can I deduce(d) how variable "records" would end
up?
Lets say I want to create list of persons, I would know I would keep some structure for example,
I have following XML
<persons>
<person>
<name>Chuck Norris</name>
<age>137</age>
</person>
<person>
<name>Donald Trump</name>
<age>19</age>
</person>
<persons>
You know you want to get the records of person your list would be declare like this, List<Person>. You know Deserialize() method returns object and you would want to read persons data, you would cast that object into List<Person>. So basically what I am trying to say is that both the question you asked are based on the assumption and choices made at the design time of you application.
I have a dbf file (dBase) that I want to read, put each row into a single list (since a row represents data about one shapefile object), and then be able to modify the list (e.g., convert fields which represent the name to a string). This means that the datatype need to be able to hold both Ints, strings, bool and so on, and add items to, it. In python I could do this with lists, but since sets cant be modified, I cant use them.
This sounds like a (exact) duplicate to Alternative to Tuples,
but it isn't. These questions are based on the assumption that you know which objects you want beforehand; I don't.
I'm on .NET 4.5, btw.
Use dynamic - it is a perfect use case for it:
Visual C# 2010 introduces a new type, dynamic. The type is a static type, but an object of type dynamic bypasses static type checking. In most cases, it functions like it has type object. At compile time, an element that is typed as dynamic is assumed to support any operation. Therefore, you do not have to be concerned about whether the object gets its value from a COM API, from a dynamic language such as IronPython, from the HTML Document Object Model (DOM), from reflection, or from somewhere else in the program. However, if the code is not valid, errors are caught at run time.
If you want to be able to easily add properties at runtime and change their types, you can use ExpandoObject with dynamic, for example:
dynamic expando = new ExpandoObject();
expando.SomeProperty = "1234";
Console.WriteLine(expando.SomeProperty);
Console.WriteLine(expando.SomeProperty.GetType().FullName); // string
expando.SomeProperty = int.Parse(expando.SomeProperty);
Console.WriteLine(expando.SomeProperty);
Console.WriteLine(expando.SomeProperty.GetType().FullName); // int
Have you tried using the dynamic type?
So lets say I have a class like
public class Complex { } // this is what I mean when I say List<Complex>
// its just a user-defined class or type if you will
Now let's say I have a method which returns a list that holds objects.
Now let's say I can further guarantee that each of these objects in the list is actually of type Complex (in other words List < Complex >)
I would like the most painless way of casting this list as possible. A one-liner would be ideal, but a few lines would be fine too.
Here is what I tried (but doesn't work - InvalidCastOperation exception):
// Sorry this is so hard to read! Also .Cast<Complex>() doesn't work either :(
return (ComplexCollection) ((List<Complex>) ((List<object>) complexElementsDictionary["ComplexElementCollection"]).OfType<Complex>());
Some specifics about this code snippet:
ComplexCollection inherits List<Complex>
complexElementsDictionary is of type (Dictionary<string, List<object>)
So in plain terms I'm asking a Dictionary<> for its corresponding list of objects. Then I try to cast this list to what its supposed to be, which is a list of Complex.
Note - Please try to ignore the fact that I am casting like this at runtime. I'm deserializing an XML collection (in app.config actually) and this is how I've chosen to do it. There may be a better way, but for now I just want to see if anyone knows a way to do what I'm asking.
Thank you so much! I hope it is clear what I'm asking, and if not I'll update the question.
Breaking up your example code and modifying it slightly to use Cast():
List<object> list = complexElementsDictionary["ComplexElementCollection"];
List<Complex> typedList = list.Cast<Complex>().ToList();
You now have a list of objects of the required type. But what you actually want is an instance of your collection object, and this cannot be obtained by another cast. That is, you can't do this:
ComplexCollection collection = (ComplexCollection)typedList;
because typedList simply isn't an instance of ComplexCollection and there is no conversion operator available to the compiler to convert from List<Complex> to ComplexCollection.
You will need to create your instance and add the Complex objects to it:
ComplexCollection collection = new ComplexCollection();
foreach(Complex c in typedList){
collection.Add(c);
}
Or in just four lines:
ComplexCollection collection = new ComplexCollection();
foreach(Complex c in complexElementsDictionary["ComplexElementCollection"].Cast<>(Complex)){
collection.Add(c);
}
To convert a List<object> to List<Complex> is as simple as:
List<object> objectList = complexElementsDictionary["ComplexElementCollection"];
List<Complex> complexList = objectList.Cast<Complex>().ToList();
However you can't cast a List<Complex> to ComplexCollection just because ComplexCollection inherits from List<Complex>. (the other way around is fine though)
List<T> has a constructor which takes an IEnumerable<T> and adds the elements to a list. So I think what you need is to add this constructor to ComplexCollection:
public ComplexCollection(IEnumerable<Complex> values) : base(values)
{
/* plus any other logic you have */
}
And then your example with the return statement becomes:
return new ComplexCollection(
complexElementsDictionary["ComplexElementCollection"].Cast<Complex>()
);
To convert a list to a new type you can just do something as simple as
(ComplexCollection)(yourList.Select(x => (complexType)x).ToList());
That should work, basically your going through your list of objects in the dictionary and casting each item to the appropriate type, then converting that to a list and then converting your list to the more specific collection type.
I'm afried there's no direct solution. Maybe you could use ConvertAll:
// ol is of type List<Object>
List<Complex> cl = ol.ConvertAll(o=>(Complex)c);
I'm working on a project for homework where I have an ArrayList containing 5 strings. I know how to select items of the ArrayList (using an index value) but not how to access the objects strings. Any help would be great. Here is what I've tried to do:
private ArrayList myComponents;
private int listIndex = 0;
myComponents = new ArrayList(); //Arraylist to hold catalog data
equipment = new Equipment(itemName, itemType, itemDetails, itemMaintenance, itemId);
myComponents.Add(equipment);
// class file is called Equipment.cs
// I know normally that equipment without the arraylist this would work:
// equipment.getitemName();
// but combining with the arraylist is being problematic.
You will likely be better off using a List instead of an ArrayList. An ArrayList is not strongly typed which means that you cannot treat the things/objects inside the array like they are "Equipment" but rather only like they are a generic boring object.
List<Equipment> myComponents = new List<Equipment> ();
equipment = new Equipment(itemName, itemType, itemDetails, itemMaintenance, itemId);
myComponents.Add(equipment);
foreach(Equipment eq in myComponents)
{
eq.getItemName();
// do stuff here
}
Let me know if this solves your problem.
An ArrayList doesn't know (or care) what kind of objects are placed in it. It treats everything put into it as an Object. When retrieving objects from the ArrayList you will need to convert the returned Object reference into a reference of the appropriate type before you can access that types properties and methods. There are several ways of doing this:
// this will throw an exception if myComponents[0] is not an instance of Equipement
Equipment eq = (Equipment) myComponents[0];
// this is a test you can to to check the type
if(myComponents[i] is Equipment){
// unlike the cast above, this will not throw and exception, it will set eq to
// null if myComponents[0] is not an instance of Equipement
Equipment eq = myComponents[0] as Equipment;
}
// foreach will do the cast for you like the first example, but since it is a cast
// it will throw an exception if the type is wrong.
foreach(Equipment eq in myComponents){
...
}
That being said, if possible, you really want to be using a generic type. The one that works most like an ArrayList is List. Generics help in a lot of cases to avoid all the casting that makes the ArrayList code painful to write and error prone. The downside is of course that you cannot mix types in a List. A List won't let you put a string in it, while an ArrayList full of Equipment instances will. The particular problem you are trying to solve will determine which makes more sense.
Since all the items in the array list are "objects" on the face of it, but they're actually Equipment objects under the covers, you need a way of going from object to Equipment when retrieving the items from the ArrayList (hint: Cast). Don't want to give it away since this is homework, but that should help....
I have been learning about the basics of C# but haven't come across a good explanation of what this is:
var l = new List<string>();
I don't know what the <string> is doing or if it's the List that is doing the magic. I have also seen objects been thrown within the < > tags.
Can someone explain this to me with examples, please?
That is the generic syntax for C#.
The basic concept is that it allows you to use a Type placeholder and substitute the actual real type in at compile time.
For example, the old way:
ArrayList foos = new Arraylist();
foos.Add("Test");
worked by making ArrayList store a list of System.Objects (The base type for all things .NET).
So, when adding or retrieving an object from the list, The CLR would have to cast it to object, basically what really happens is this:
foos.Add("Test" as System.Object);
string s = foos[1] as String.
This causes a performance penalty from the casting, and its also unsafe because I can do this:
ArrayList listOfStrings = new ArrayList();
listOfStrings.Add(1);
listOfStrings.Add("Test");
This will compile just fine, even though I put an integer in listOfStrings.
Generics changed all of this, now using Generics I can declare what Type my collection expects:
List<int> listOfIntegers = new List<int>();
List<String> listOfStrings = new List<String>();
listOfIntegers.add(1);
// Compile time error.
listOfIntegers.add("test");
This provides compile-time type safety, as well as avoids expensive casting operations.
The way you leverage this is pretty simple, though there are some advanced edge cases. The basic concept is to make your class type agnostic by using a type placeholder, for example, if I wanted to create a generic "Add Two Things" class.
public class Adder<T>
{
public T AddTwoThings(T t1, T t2)
{
return t1 + t2;
}
}
Adder<String> stringAdder = new Adder<String>();
Console.Writeline(stringAdder.AddTwoThings("Test,"123"));
Adder<int> intAdder = new Adder<int>();
Console.Writeline(intAdder.AddTwoThings(2,2));
For a much more detailed explanation of generics, I can't recommend enough the book CLR via C#.
It's generics - it's a form of type parameterisation. In your example, it's making l refer to a list of strings - the list will only ever contain strings: the compiler treats it (pretty much) as if everywhere that the API docs mention "T" it actually says "string". So, you can only add strings to it, and if you use the indexer you don't need to cast to string, etc.
To be honest, giving generics detailed coverage on an online forum is pretty much impossible. (In C# in Depth, I take nearly 50 pages talking about generics.) However, armed with the name of the feature, you should be in a much better position to find out more. The MSDN "Introduction to C# Generics" is probably a good starting point.
Asking specific questions about generics on SO is likely to yield good results - I just don't think it can really be covered properly in one question/answer.
This is .NET Generics. The type within the < > denotes the type of element contained in the list.
with ArrayList you'd have to cast the elements inside...
int x = (int)myArrayList[4];
with List you can avoid that step because the compiler already knows the type.
int x = myList[4];
Generics are available in .NET 2.0 and later.
Those are generics. You are making a List that only contains strings. You could also say
List<int>
and get a list that only contains ints.
Generics is a huge topic, too big for a single answer here.
Those are known as Generics (specifically List is a generic class).
Reading from MSDN
Generics (C# Programming Guide)
An Introduction to C# Generics
Generics in the .NET Framework
This is generics in action. A regular List stores items of type Object. This requires casting between types. This also will allow you to store any kind of item in one instance of a list. When you are iterating through items in that list you cannot be sure that they are all of a certain type (at least not without casting each item). For instance lets say you create a list like this:
List listOfStrings = new List();
Nothing prevents someone from doing something like this:
listOfStrings.add(6); //Not a string
A generic list would allow you to specify a strongly-typed list.
List<string> listOfStrings = new List<string>();
listOfStrings.add("my name"); //OK
listofStrings.add(6); //Throws a compiler error
There is a more thorough examples on here Generics
< > is for generics. In your specific example, it means that the List is a List of strings, not say a list of ints.
Generics are used to allow a type to be, well, generic. It's used ALOT in Collections to allow them to take different types so that they can function much like a normal array and still catch invalid types being assigned at compile time. Basically it allows a class to say "I need to be associated with some specific type T, but I don't want to hard code exactly what that type is, and let the user select it.". A simple array for instance might look something like:
public class MyArray<T> {
private T[] _list;
public MyArray() : this.MyArray(10);
public MyArray(int capacity)
{ _list = new T[capacity]; }
T this[int index] {
get { return _list[index]; }
set { _list[index] = value; }
}
}
Here, we have a private list of type T that is accessed by using our class like a normal array. We don't care what type it is, it doesn't matter to our code. But anyone using the class could use it as, say MyArray<string> to create a list of strings, while someone else might use it as MyArray<bool> and create a list of flags.