Accessing my objects array that has not been defined as an array - c#

I wanted to use some amfphp functions in .NET and get access to some objects. After some searching I found a piece an opensource gateway that would do the trick.
How to use AMFPHP functions from .NET WPF application?
Ok here is were I am right now , and I could really use some help. After having made the connection and proper calls
public void Connect()
{
// Create NetConnection client
_netConnection = new NetConnection();
_netConnection.ObjectEncoding = ObjectEncoding.AMF0;
_netConnection.NetStatus += new NetStatusHandler(_netConnection_NetStatus);
_netConnection.Connect("http://www.mytestserver.nl/services/gateway");
System.Console.WriteLine("*** Flash RPC ***");
_netConnection.Call("amfphp.mytestserver.getObjects", new GetCustomersHandler(), new object[] { "415" });
System.Console.WriteLine("Press 'Enter' to exit");
}
And in my handler
public class GetCustomersHandler : IPendingServiceCallback
{
public void ResultReceived(IPendingServiceCall call)
{
object result = call.Result;
System.Console.WriteLine("Server response: " + result);
//DataAccess sample sends back an ArrayCollection (AMF3)
ArrayCollection items = result as ArrayCollection;
foreach (object item in items)
{
Flex.CustomerVO customer = item as Flex.CustomerVO;
System.Console.WriteLine(customer.firstname + " " + customer.lastname);
}
}
}
This is the way it is done in the project given in the samples folder.
I cannot iterate through the items , so I figured let me see how I can access my results object.
And here is were is it (at least for me) getting a bit tricky.
I can see the results as type object in my list , I can access the result array (?object) , but how do I iterate through my results objects in code since it is not an array. To clarify I added some screenshots.
http://imageshack.us/f/685/fluorine1.png/
as can be seen here results containing 46 items.
a little more clarification
http://imageshack.us/f/38/fluorine2.png/
(For instance I wish to access the Key, Value and such).
Does anyone have a solution or approach. It doesn't feel difficult(perhaps it is) but I seem to missing something.
Some help anyone?

It is indeed an array. It is an array of objects (object[]). You can access this like is shown in the example. The only problem is that you have to know what kind of object it is and cast it to that type.
Flex.CustomerVO customer = item as Flex.CustomerVO;
is where they cast the object.

If you want to iterate over the objects, you need to cast your result to an array of objects:
object[] objects = (objects)result;
Then you can access the individual items by casting again:
foreach (object obj in objects)
{
FluorineFx.ASObject asObject = (FluorineFx.ASObject)obj;
System.Console.WriteLine(asObject.Key);
}

Related

C# - Getting the 3 lowest values in a List, measured by a public property of the objects within the List

Sorry if my terminology is not great, I'm not a professional programmer.
I have a List< Something >, whereby the 'Something' is a struct. This struct contains objects, which each have their own public properties/fields in the classes. I want to sort the list in order - but by the values found in these nested properties/fields. Then I want to return a list of these values, not the structs.
I know this is very confusing but I've had trouble trying to do it. At the moment I just get a list returned with a count of 20 (which is the full data set I'm using), but I want the 3 values only with the smallest value.
For context and further explanation, here is some code I'm using:
// Returns 3 nearest stations to the location specified
public static List<TrainStation> nearbyStations(GeoCoordinate location)
{
List<StationWalk> stations = new List<StationWalk>();
foreach (TrainStation s in All)
{
stations.Add(new StationWalk(s, new Walk(location, s.location)));
}
// return 3 TrainStation objects that have the lowest StationWalk.Walk.duration values corresponding with them in the StationWalk struct
stations.OrderBy(walks => walks.walk.duration).Take(3);
List<TrainStation> returnList = new List<TrainStation>();
foreach (StationWalk s in stations)
{
returnList.Add(s.station);
}
return returnList;
}
private struct StationWalk
{
public StationWalk(TrainStation station, Walk walk)
{
this.station = station;
this.walk = walk;
}
public TrainStation station;
public Walk walk;
}
'Walk' is a class that contains a 'duration' field. This represents the time it takes to walk. More specifically, my overall goal here is to figure out which 3 walks are the fastest walks out of all 20 in the list. But the 'walks' are properties of the StationWalk struct, and the 'duration' is a property of the Walk.
How would I go about doing this? Really sorry if this isn't well explained, it's confusing to myself despite writing it myself, yet alone trying to explain it to others.Appreciate any help.
The OrderBy and Take both return a new collection, they do not modify the existing collection, so you would need to store the reference to new collection returned by the methods like:
stations = stations.OrderBy(walks => walks.walk.duration).Take(3).ToList();
and if you want to keep reference to the original list for further usage down in your code, then just store the result in a local variable:
var lowestThreeStations = stations.OrderBy(walks => walks.walk.duration).Take(3).ToList();

C# Iterating over a dictionary passed as a generic

I am having trouble trying to iterate over a dictionary passed to a function as a generic. For example, I have a function that loads data from a DB.
public T Load<T>(...)
This function can be called like so, with which I have no problems;
someclasstype data = Load<someclasstype>(...);
List<someclasstype> data = Load<List<someclasstype>>(...);
I've recently tried to extend this to be able to deal with dictionaries as well, and calling it like so:
Dictionary<long, someclasstype> data = Load<Dictionary<long, someclasstype>>(...)
I can load the data without a problem and store it in the dictionary no problem.
At this stage, the dictionary, with all its keyvaluepairs is stored in a variable called result, and I'm creating an IEnumerable with
IEnumerator resultIdx = ((IEnumerable)result).GetEnumerator();
if (!resultIdx.MoveNext())
return (T)result;
object kvp = resultIdx.Current;
So far so good. I can see the value of the key and the value of the value in a watch, or by mouseover on the kvp variable.
But I cannot figure out how to get the value part of the keyvaluepair from kvp.
// None of these work - I get compile time errors, unboxing errors, or invalid cast errors.
object item = ((KeyValuePair<TKey, TValue>)kvp).Value;
object item = ((KeyValuePair<long, object>)kvp).Value;
object item = ((T)kvp).Value // Never had a hope for this, but desperation...
Does anyone have any idea how I can do this?
try adding dynamic kvp = resultIdx.Current; . Then you can use kvp.Value
You can rewrite the function into two functions like.
public T Load<T>(...)
//Or maybe public List<T> Load<T>(...)
and
public Dictionary<long, T> LoadD<T>(...)
Then you can cast result to KeyValuePair<long, T> in LoadD. You can call Load from LoadD to minimize code rewriting.
Answer provided by Dede in comments:
"Use Reflection ?
object key kvp.GetType().GetProperty("Key").GetValue(kvp);
object value kvp.GetType().GetProperty("Value").GetValue(kvp);
Not very optimized, but can work... – Dede 24"

C# List being treated as a pointer not a container of objects

I think I have figured out what is going on here, but I would like some confirmation. (code is at the bottom of the question)
I have a List object which I need to make a copy of.
The ways I have attempted this have been by creating another new List of the same type then using the '=' operand, I also tested with the AddRange method and got the same results.
No matter how I manipulate the copy of the List it applies the manipulations to the original as well.
I believe it is because C# is using lists as a reference/pointer structure rather than as object/value. Is this correct?
temp1.AddRange(list1);
temp2.AddRange(list2);
foreach(record item in temp1)
{
foreach (KeyValuePair<string, string> itemB in temp2.First().data)
{
item.data.Add(itemB.Key, null);
ERRORDATA = "item data state:" + item.ToString() + "\r\nitemB key:[" + itemB.Key + "] " + itemB.Value;
}
}
temp1.First().data.Add("DOOBY", "doo");
after this executes, list1 has inserted the dooby,doo key/value pair when it should have only done that to the temp1 object.
cheers for any answers.
It looks to me like you are confusing a change to the "list" temp1 with a change to the objects held by each list. The objects held by each list are just references to the objects, so a change made to the object in one list will be reflected in the other lists. However if you did a temp1.Add(o), o would not be added to temp2.

Is there a way to make string a reference type in a collection?

I want to modify some strings that are contained in an object like say an array, or maybe the nodes in an XDocument (XText)XNode.Value.
I want to gather a subset of strings from these objects and modify them, but I don't know at runtime from what object type they come from.
Put another way, let's say I have objects like this:
List<string> fruits = new List<string>() {"apple", "banana", "cantelope"};
XDocument _xmlObject;
I want to be able to add a subset of values from the original collections to new lists like this:
List<ref string> myStrings1 = new List<ref string>();
myStrings1.Add(ref fruits[1]);
myStrings1.Add(ref fruits[2]);
List<ref string> myStrings2 = new List<ref string>();
IEnumerable<XNode> xTextNodes = getTargetTextNodes(targetPath); //some function returns a series of XNodes in the XDocument
foreach (XNode node in xTextNodes)
{
myStrings2.Add(((XText)node).Value);
}
Then change the values using a general purpose method like this:
public void Modify(List<ref string> mystrings){
foreach (ref string item in mystrings)
{
item = "new string";
}
}
Such that I can pass that method any string collection, and modify the strings in the original object without having to deal with the original object itself.
static void Main(string[] args)
{
Modify(myStrings1);
Modify(myStrings2);
}
The important part here is the mystrings collection. That can be special. But I need to be able to use a variety of different kinds of strings and string collections as the originals source data to go in that collection.
Of course, the above code doesn't work, and neither does any variation I've tried. Is this even possible in c#?
What you want is possible with C#... but only if you can fix every possible source for your strings. That would allow you to use pointers to the original strings... at a terrible cost, however, in terms of memory management and unsafe code throughout your application.
I encourage you to pursue a different direction for this.
Based on your edits, it looks like you're always working with an entire collection, and always modifying the entire collection at once. Also, this might not even be a string collection at the outset. I don't think you'll be able to get the exact result you want, because of the base XDocument type you're working with. But one possible direction to explore might look like this:
public IEnumerable<string> Modify(IEnumerable<string> items)
{
foreach(string item in items)
{
yield return "blah";
}
}
You can use a projection to get strings from any collection type, and get your modified text back:
fruits = Modify(fruits).ToList();
var nodes = Modify( xTextNodes.Select(n => (XText)n.Value));
And once you understand how to make a projection, you may find that the existing .Select() method already does everything you need.
What I really suggest, though, is that rather than working with an entire collection, think about working in terms of one record at a time. Create a common object type that all of your data sources understand. Create a projection from each data source into the common object type. Loop through each of the objects in your projection and make your adjustment. Then have another projection back to the original record type. This will not be the original collection. It will be a new collection. Write your new collection back to disk.
Used appropriately, this also has the potential for much greater performance than your original approach. This is because working with one record at a time, using these linq projections, opens the door to streaming the data, such that only one the one current record is ever held in memory at a time. You can open a stream from the original and a stream for the output, and write to the output just as fast as you can read from the original.
The easiest way to achieve this is by doing the looping outside of the method. This allows you to pass the strings by reference which will replace the existing reference with the new one (don't forget that strings are immutable).
And example of this:
void Main()
{
string[] arr = new[] {"lala", "lolo"};
arr.Dump();
for(var i = 0; i < arr.Length; i++)
{
ModifyStrings(ref arr[i]);
}
arr.Dump();
}
public void ModifyStrings(ref string item)
{
item = "blah";
}

How to read an array of objects

I have a C# list of objects and I'm trying to access its nested object. Here's the structure from Visual Studio's debugger (sorry I can't embed images since I'm a newbie to the site):
>product.Product {Product.AxdEntity_Product_EcoResProduct[1]}
>> - [0] {Product.EcoResProductMaster} // #1 - Please note curley braces
>>> - [Product.EcoResProductMaster] // #2 - Please note brackes
>>> + base {Product....
>>> + ModelingPolicy
>> + Identifier
To access the properties in #1, I would do the following:
var prod = product.Product[0];
Then I can access "Identifier" as such:
var identifier = prod.Identifier[0]...
To access the properties in #2 (such as ModelingPolicy), I'm not sure how to go about it:
var prod = product.Product[0][WhatShouldGoHere?].ModelingPolicy[0] ...?? I need help here
Eventually, I'd like to access the ModelingPolicy[0] like I did with prod.Identifier[0].
The Product class is being returned from a web service and I don't have access to its definition. At least I don't think I do.
Thank you for any guidance!
Looks to me like:
var ecoResProductMaster = product.Product[0].EcoResProductMaster; // Product type
var modelingPolicy = ecoResProductMaster.ModelingPolicy;
Have you tried this?
var productList = product.ToList()
foreach(var prod in productList)
{
var identifier = prod.identifier
foreach (var modelingPolicy in identifier.ModelingPolicy)
{
//do somthing with modeling policy
}
//do more stuff with product
}
As an aside please sort your naming conventions out. Having an array called product that contains a number of Product objects is just confusing
It's difficult to tell what you're going for here. Is this a List or array?
If it is a list then you can just foreach through the list to access each object.
Like if you have
List<SomeObject> someObjectList = new List<SomeObject>();
Then after you add a bunch of SomeObjects to the List you can just access the SomeObjects in a foreach loop.
foreach (SomeObject s in someObjectList)
{
// then to access nested objects
var n = s.SomeNestedObject;
// do something with n
}
Thanks all for your input. The answer from SmartDev helped me access the objects in the inner array. To do this, simply do the following:
var productMaster = (EcoResProductMaster)product.Product[0];
var modelingPolicy = productMaster.ModelingPolicy[0];
Of course, this is assuming that only one object is returned in the array, hence "[0]" but this should eventually go inside a foreach loop.
What I learned was if an object is returned without an index such as //#2 as noted above, a type cast should allow me to access it. However, if an index is returned such as //#1, then using [0] will allow me to access its properties.

Categories

Resources