Recursively remove key from Generic C# Object - c#

I am trying to visualize a C# object which is a SyntaxTree. JSON would be nice, but not required, I am just having a hard time dealing with the VS UI and all the circular references in the object. when I try to use JSON.NET to serialize it, I get a circular reference error. This isn't the first time I have run into a similar problem, but I thought I would work on it for a bit.
I know which keys need to be removed, they are ContainingElement, ContainingNamSpace, ContainingSourceUnit, ContainingType.
I was trying to create a function that could be reused to recursively remove those keys from the object before I pass it to JSON.NET, but I need some help.
public static object removeObjectsByName(object incoming, string WildcardRemove){
List<object newObject = new List<object>();
foreach (var item in incoming)
{
if (subItem.ToString().Contains(WildcardRemove))
{
continue;
}
}
removeObject(newObject);
return newObject;
}
I don't typically do a lot with generic types, but I don't know what all the incoming types of data will be, especially as we call it recursively. Should we create a List, Array, or leave it an object? Here is a sample of what I am looking at:
The root of the object is named tree, I am specifically interested in the Functions which has 61 items in the array. As you dig into those you start to find the Containing* keys that need to be removed. Trouble is that they will also exist under Body and Properties. Then under Body, there is another Properties which will have it's Containing*.
I don't need any of that back referencing stuff, I just want each child without any keys named Containing*.
Any tips? Again, I don't care if the output is JSON, to the Console, as a List, if we use Linq or what, just trying to see my way through this.

Related

Neo4JClient cannot retrieve Dictionary with values as objects

Need help with Neo4Client, if I run fluent cypher query and use
.Return(node => node.As<Dictionary<string,string>>()) it returns both correct keys and values albeit with loss of a datatype, but if I use .Return(node => node.As<Dictionary<string,object>>()) it returns dictionary with keys, but no values that I can see. The debugger shows {object}, but I cannot cast it to anything - the field that I know is a string returns null when casting - obj as string. Same happens with Dictionary<<string, dynamic>>. What is this object and how can I retrieve my dictionary back from Neo4j using client?
Writing up the result of a Gitter conversation, and discussion here.
So this is down to the way Neo4jClient deserializes objects back, specifically the OGM (Object Graph Mapping) side of things. Basically it treats Dictionary<string, object> in a bespoke way, which in the long run Activates a new object instance, hence the objects actually being object instances, and not a string or equivalent.
There's no way (at present) around this without changing the OGM side of things substantially.

Seeking guidance reading .yaml files with C#

Two months later:
The YAML (Eve Online blueprint.yaml) file I tried to parse changed a huge deal which also made it much easier to parse using de deserializer. If someone (for whatever reason) would like to see the code, it's updated on https://github.com/hkraal/ParseYaml
Based on the comment of Steve Wellens I've adjusted the code to do less things at once. It didn't matter in the error itself. I've created another project (Example1) in my solution to test the actual example found on aaubry.net I referenced to earlier.
It gave me the same error when using an "dynamic" key which lead to my current conclusion:
There is a difference between:
items:
- part_no: A4786
and
items:
part_no: A4786
The first is being used in the example which I (wrongly) assumed I could apply to my .yaml file which is using the second syntax.
Now it remains to find out how I can get the 'child' elements of my key with the syntax used in my yaml file...
As C# is used at work I started thinking about a nice project to learn about various aspects of the language while having a direct goal to work towards. However I'm hitting my first wall quite early in my project parsing a Yaml file. My goal is to create an List of YamlBlueprint objects as defined in YamlBlueprint.cs but I don't even get to the end of the Yaml file.
I've setup a testcase on github which demonstrates the problem:
https://github.com/hkraal/ParseYaml
The example on http://www.aaubry.net/page/YamlDotNet-Documentation-Loading-a-YAML-stream works up untill I want to loop trough the items. Based on what I see I should be able to give myKey as parameter to the YamlScalarNode() to access the items below it.
var items = (YamlSequenceNode)mapping.Children[new YamlScalarNode(myKey)];
I'm gettting the following error if I do:
An unhandled exception of type 'System.InvalidCastException' occurred in yamldotnet.exe
Additional information: Unable to cast object of type 'YamlDotNet.RepresentationModel.YamlMappingNode' to type 'YamlDotNet.RepresentationModel.YamlSequenceNode'.
When passing "items" as parameter to YamlScalarNode() it just complains about the item not being there which is to be expected. As I'm not sure where my toughttrain is going wrong I would love a bit assistance on how to troubleshoot this further.
Your question has already been correctly answered, but I would like to point out that your approach is probably not the best one for parsing files. The YamlDotNet.RepresentationModel.* types offer an object model that directly represents the YAML stream and its various parts. This is useful if you are creating an application that processes or generates YAML streams.
When you want to read a YAML document into an object graph, the best approach is to use the Deserializer class. With it you can write your code as follows:
using(var reader = File.OpenText("blueprints.yaml")
{
var deserializer = new Deserializer();
var blueprintsById = deserializer.Deserialize<Dictionary<int, YamlBlueprint>>(reader);
// Use the blueprintsById variable
}
The only difference is that the Id property of the YamlBlueprint instances won't be set, but that's just a matter of adding this:
foreach(var entry in blueprintsById)
{
entry.Value.Id = entry.Key;
}
You have too much stuff going on in one line of code. Create a new YamlScalarNode object in one line, access the array in another line, cast the resultant object in another line. That way, you'll narrow down the problem area to a single step.
The message is telling you that you are retrieving a YamlMappingNode from the array but you are casting it to a YamlSequenceNode. Which is not allowed since the two types are obviously not related.
Well that was kinda stupid... it's kind of hard to create an mapping of something which only contains one element. I've edited the repo linked in the OP with an working example in case somebody runs into the same problem.

JSON.NET silently ignores circular references and sets arbitrary links in the chain to null to resolve them

I'm trying to serialize an object graph in JSON.NET in which a Galaxy contains StarSystems, a StarSystem contains Planets, a Planet contains a Colony, a Colony has an Owner, and the Galaxy also has a list of Empires, each of which has a list of explored StarSystems. So there's a circular reference between StarSystem, Planet, and Empire.
What I don't understand is the behavior I get when I serialize the object graph. Instead of throwing an error when I have the reference loop handling set to the default, and trying to serialize everything when I have it set to serialize mode, it seems to be serializing a few links in the chain, then giving up and setting arbitrary values (in my case the explored star systems) to null. Naturally this is causing crashes elsewhere in the application when it looks for star systems but finds only nulls!
Could this have something to do with the fact that some of the links in the chain are not direct references, but collections? E.g. an empire does not have one explored star system, but a list of them.
So how can I make JSON.NET serialize everything? Do I need to eliminate the circular references and just pass around ID's of objects instead of actual object references in my object model? I really don't want to do that just for serialization purposes!
I came up with a workaround. Instead of each empire storing a list of explored star systems, each star system will store a list of empires that have explored it. This way, no circular references!
Not sure how I did this, but it looks like now I'm just getting null added to the list of explored star systems, instead of replacing the list of explored star systems, so I can just filter it out. Sorry I don't have any clue what I did to fix this!

Referring to an item in an IEnumerable with no ID

So I may have coded myself into a corner, and I want to know the best way out.
I have this document editor I'm writing, and one property of the documents being edited is a list of structures. The document is stored as XML, so each of these structures is an XML node and its properties. My Document class exposes these structures as an IEnumerable.
In my editor, I want to literally highlight these structures when the mouse is nearby. I've already done the task of identifying one close to the cursor. But now I have to be able to refer to that instance of the structure, and store that somewhere. Finding the closest one just iterates through the IEnumerable, and returns the structure itself. I suppose that I could use the structure itself as the reference, but then I'm going to wind up saying in my display code if (thing == nearestThing) and it's going to do a hash code comparison or something, right?
That feels like the wrong way to do it, but I don't have a proper ID for these structures either. Suggestions?
There is no problem with that way. Keep in mind though, you should make sure that == (and to a greater extend, Equals and GetHashcode) reliably produce the same results for the same inputs.

(Deep) comparison of an object to a reference in unit tests (C#)

In a Unit Test (in Visual Studio 2008) I want to compare the content of a large object (a list of custom types, to be precise) with a stored reference of this object. The goal is to make sure, that any later refactorings of the code produces the same object content.
Discarded Idea:
A first thought was to serialize to XML, and then compare the hardcoded strings or a file content. This would allow for easy finding of any difference. However since my types are not XML serializable without a hack, I must find another solution. I could use binary serialization but this will not be readable anymore.
Is there a simple and elegant solution to this?
EDIT: According to Marc Gravell's proposal I do now like this:
using (MemoryStream stream = new MemoryStream())
{
//create actual graph using only comparable properties
List<NavigationResult> comparableActual = (from item in sparsed
select new NavigationResult
{
Direction = item.Direction,
/*...*/
VersionIndication = item.VersionIndication
}).ToList();
(new BinaryFormatter()).Serialize(stream, comparableActual);
string base64encodedActual = System.Convert.ToBase64String(stream.GetBuffer(), 0, (int)stream.Length);//base64 encoded binary representation of this
string base64encodedReference = #"AAEAAAD....";//this reference is the expected value
Assert.AreEqual(base64encodedReference, base64encodedActual, "The comparable part of the sparsed set is not equal to the reference.");
}
In essence I do select the comparable properties first, then encode the graph, then compare it to a similarly encoded reference.
Encoding enables deep comparison in a simple way. The reason I use base64 encoding is, that I can easily store the reference it in a string variable.
I would still be inclined to use serialization. But rather than having to know the binary, just create an expected graph, serialize that. Now serialize the actual graph and compare bytes. This is only useful to tell you that there is a difference; you'd need inspection to find what, which is a pain.
I would use the hack to do XML comparision. Or you could use reflection to automaticaly traverse object properties (but this will traverse ALL of them, also some you could not want to).
I would make each custom type inherit IComparable, and provide equality methods, that compare each custom types, as well as making the main class ICompareble, You can then simply compare the 2 objects ( if you have them in memory when running unit tests) If not then I would suggest either serializing, or defining constants which you expect the refactored object to have.

Categories