So I searched whole morning but couldn't find satisfactory answer
I am trying to write a generic method (service) which take an object as an input (can be JObject or Document or dynamic) and queries the collection for the properties in the object.
Example - if you send {"name": "abc"} I will search for name="abc" in any of the documents. if you send {"name":"abc", "department":"xyz"}, it searches on both fields.
Question - what should be the best input for the method?
Options -
1. public bool Exists(Document doc) //assume I already have Collection.Selflink the class.
I cannot seem to iterate through properties of the doc object.
public bool Exists(JObject obj)
I will have to iterate through the obj and prepare the query myself.
Is there any easier way to just see if the doc matches any of the documents in the collection. I am just interested in matching those fields present in the document.
Thanks in advance!
This isn't supported out of the box.
I would imagine a bit of custom code that iterated over the object passed in and appended each property to a where clause in SQL or Linq would likely solve the problem.
It could start to get messy with nested objects and arrays though.
If this is something you would like to see supported natively, please vote for it http://feedback.azure.com
Related
I'm writing a source generator in C#, and I've got 2 objects that I need to compare to see if they relate to the same class, but I can't find a way to do it.
My first object is an instance of ClassDeclarationSyntax. This is coming from my custom ISyntaxContextReceiver to find classes that match specific conditions.
Elsewhere in my generator I have an IdentifierNameSyntax object, which is coming from looking at the types within a TypeOfExpressionSyntax that I find within a different class's list of attributes.
I need to compare the two objects here to see if they are talking about the same thing.
With the IdentifierNameSyntax I can get the type information by using the semantic model:
ITypeSymbol semanticType = semanticModel.GetTypeInfo(targetType).Type;
But I don't know how to compare this ITypeSymbol against ClassDeclarationSyntax either.
Is there a way to do this, or is there a way to get the semantic model type information for a ClassDeclarationSyntax object?
The method you are looking for is GetDeclaredSymbol on semanticModel. As you can see from the documentation, there are huge number of overloads which will allow you to get the associated symbol information for not only classes, but also fields, methods, properties, events, parameters, and so forth. Definitely a method you'll want to keep in your back pocket!
I have a large complex XSD set.
I have C# classes generated from those XSDs using xsd.exe. Naturally, though the majority of properties in the generated classes are strings, many are decimals, DateTimes, enums or bools, just as they should be.
Now, I have some UNVALIDATED data that is structured in the correct XML format, but may well NOT be able to pass XSD validation, let alone be put into an instance of the relevant .Net object. For example, at this stage, for all we know the value for the element that should be a DateTime could be "ABC" - not even parseable as a DateTime - let alone other string elements respecting maxLength or regex pattern restrictions. This data is ready to be passed in to a rules engine that we already have to make everything valid, including defaulting things appropriately depending on other data items, etc.
I know how to use the various types in System.Xml to read the string value of a given element by name. Clearly I could just hand craft code to get out all the elements that exist today by name - but if the XSD changes, the code would need to be reworked. I'd like to be able to either directly read the XSD or use reflection on the generated classes (including attributes like [System.Xml.Serialization.XmlTypeAttribute(TypeName=...] where necessary) to find exactly how to recursively query the XML down to the the raw, unverified string version of any given element to pass through to the ruleset, and then after the rules have made something valid of it, either put it back into the strongly typed object or back into a copy of the XML for serialization into the object.
(It has occurred to me that an alternative approach would be to somehow automatically generate a 'stringly typed' version of the object - where there are not DateTimes etc; nothing but strings - and serialize the xml into that. I have even madly thought of taking the xsd.exe generated .cs file and search/replacing all the enums and base types that aren't strings to strings, but there has to be a better way.)
In other words, is there an existing generic way to pull the XElement or attribute value from some XML that would correspond to a given item in a .Net class if it were serialized, without actually serializing it?
Sorry to self-answer, and sorry for the lack of actual code in my answer, but I don't yet have the permission of my employer to share the actual code on this. Working on it, I'll update here when there is movement.
I was able to implement something I called a Tolerant XML Reader. Unlike most XML deserializing, it starts by using reflection to look at the structure of the required .Net type, and then attempts to find the relevant XElements and interpret them. Any extra elements are ignored (because they are never looked for), any elements not found are defaulted, and any elements found are further interpreted.
The main method signature, in C#, is as follows:
public static T TolerantDeserializeIntoType<T>(
XDocument doc,
out List<string> messagesList,
out bool isFromSuppliedData,
XmlSchemaSet schemas = null,
bool tolerant = true)
A typical call to it might look like this:
List<string> messagesList;
bool defaultOnly;
SomeType result = TolerantDeserializeIntoType<SomeType>(someXDocument, out messagesList, out defaultOnly);
(you may use var; I just explicitly put the type there for clarity in this example).
This will take any XDocument (so the only criteria of the original was that it was well-formed), and make an instance of the specified type (SomeType, in this example) from it.
Note that even if nothing at all in the XML is recognized, it will still not fail. The new instance will simply have all properties / public fields nulled or defaulted, the MessageList would list all the defaulting done, and the boolean out paramater would be FALSE.
The recursive method that does all the work has a similar signature, except it takes an XElement instead of an XDocument, and it does not take a schemaSet. (The present implementation also has an explicit bool to indicate a recursive call defaulting to false. This is a slightly dirty way to allow it to gather all failure messages up to the end before throwing an error if tolerant is false; in a future version I will refactor that to only expose publicly a version without that, if I even want to make the XElement version public at all):
public static T TolerantDeserializeXElementIntoType<T>(
ref XElement element,
ref List<string> messagesList,
out bool isFromSuppliedValue,
bool tolerant = true,
bool recursiveCall = false)
How it works, detail
Starting with the main call, the one with with an XDocument and optional SchemaSet:
If a schema Set that will compile is supplied (actually, it also looks for xsi:noNamespaceSchemaLocation as well) the initial XDocument and schemaSet call runs a standard XDocument.Validate() across the supplied XDocument, but this only collects any issued validation error callbacks. It won't throw an exception, and is done for only two reasons:
it will give some useful messages for the MessageList, and
it will populate the SchemaInfo of all XElements to
possibly use later in the XElement version.
(note, however, that the
schema is entirely optional. It is actually only used to resolve
some ambiguous situations where it can be unclear from the C#
object if a given XElement is mandatory or not.)
From there, the recursive XElement version is called on the root node and the supplied C# type.
I've made the code look for the style of C# objects generated by xsd.exe, though most basic structured objects using Properties and Fields would probably work even without the CustomAttributes that xsd.exe supplies, if the Xml elements are named the same as the properties and fields of the object.
The method looks for:
Arrays
Simple value types, explicitly:
String
Enum
Bool
then anything
else by using the relevant TryParse() method, found by reflection.
(note that nulls/xsi:nill='true' values also have to be specially
handled)
objects, recursively.
It also looks for a boolean 'xxxSpecified' in the object for each field or property 'xxx' that it finds, and sets it appropriately. This is how xsd.exe indicates an element being omitted from the XML in cases where null won't suffice.
That's the outline. As I said, I may be able to put actual code somewhere like GitHub in due course. Hope this is helpful to someone.
I've tried some examples on here but am tearing my hair out.
I do a query and it returns JSON, inside the JSON are lots of hashes, eg.
{ "gjwiegjeigj": { ....}, "gjeeigjwoeigj": {...} ... }
I want to loop through each of these, and deserialize the contents into an object.
I've created the object, myObject which has all the fields, but I am stuck on deserialising.
I can deserialise straight from the base object using JsonConvert.DeserializeObject but I can't do that, I need to loop through and do that to the children.
I want an array of my custom objects with all the fields taken from the Json as a result of this, I don't care about the title of each one (the garbage hash).
Any ideas? I know I can loop through, which gives me lots of JTokens but that's where I get stuck.
Edit: Reading your question again, you mention both knowing and not knowing all the fields. It sounds like you really don't know exactly what fields the JSON string will contain.
For cases like this, I suggest you use dynamic -- this is where it shines. If you do know all the field names, your class should be deserializing without any issue.
What have you tried? Show us some real code, and real exceptions or problems.
To deserialize into a list of dynamic objects is simple:
dynamic toReturn = JsonConvert.DeserializeObject<List<dynamic>>(rawJson);
You should get back a list of dynamic objects. You can poke it for the fields you want:
Console.WriteLine(toReturn.First().gjwiegjeigj);
So I figured it out, basically to get from a collection JTokens which is what I get when I iterate through .Children() on my JSON object, I can either cast it to a JProperty and do .Name to get the name or .Value to get the value, or I can deserialize directly into an object, essentially like this:
MyObject record = (MyObject)JsonConvert.DeserializeObject(myRow.Children().First().ToString(), typeof(MyObject), settings);
Then I don't know need to know the name of the property I am deserializing.
I want to create a dynamic object from a string of XML. Is there an easy way of doing this?
Example String.
<test><someElement><rep1>a</rep1><rep1>b</rep1></someElement></test>
I'm trying to create an mvc editor for passing data through nvelocity and would like people on the front end to input xml as there data for parsing.
Thanks in advance.
You need 2 things to achieve this :
1) Valid xml
2) C# class which has same data members as in your input xml.
You need to create one object of C# class then enumerate through all the elements of xml and when by using switch for each of the element name, you can take inner text property of that element and assign it to respective data member of object.
C# code might look like following (you need to fill in the gaps):
class test {
List<string> someElement;
}
class xmlEnum
{
static test createObject(string inputXml)
{
test t = new test();
// load input xml in XmlDocument class
// and start iterating thorugh all the elements
swithc(elementName)
{
case rep1:
t.someElement.add(element.innerText);
break;
// some more cases will go here
}
// finally return the object;
return t;
}
}
I hope this will help you.
I don't think there's a ready-made dynamic solution to this. If I understand your question correctly, you would like to do something like this.
SomeDynamicXmlObject test = new SomeDynamicXmlObject(yourteststring);
var rep1 = test.SomeElement.rep1;
The closest I can think of you could get to that, is to use XElement classes, something like this:
XElement test = XElement.Parse(yourteststring);
var rep1 = test.Element("SomeElement").Element("rep1");
If that's not good enough, I'm afraid you will have to write something yourself that will parse the xml and create the object on the fly. If you know in advance what the xml will look like, you could use shekhars code, but I guess from your comments that you don't.
If you have schema for xml available and if this is needed in dev/build environment then a round about way to do this will be
Use XSD tool to parse schema and generate code from it
Build the generated code using command line complier or compiler services to generate assmebly. Now you have a type available there that can be used.
Needless to say this will be a quite slow and out-of-proc tools will be used here.
Another (not an easy way but faster) way that would not have dev env dependencies would be to parse your xml and generate dynamic type using reflection. See this article to check how to use Reflection.Emit
This may seem like a simple question however i've spent the last hour trying to solve this.
I want to create a custom subsonic collection so that i can fill it with data from a query with multiple joins using the .ExecuteAsCollection<>(); method.
i've created the custom class and a custom collection and even a controller with the load method but i keep getting a null refernce exception from the ExecuteAsCollection<>();
the stack track says its an error coming from the SubSonic.Load method.
i have left out the class's "SQLProps" that all the other subsonic classes have, but i was hoping i wouldn't have to go through each field painstakingly.
There has to be something simple i'm missing. Can someone who's done this give me a quick run down on what is required by subsonic to fill a custom collection with a query?
thanks
Doug
UPDATE:
i forgot to mention that i also added the public Columns struct with all my columns.
ExecuteAsCollection<T>() will only work with SubSonic-generated collections. You can map the result of a query to an arbitrary object type with ExecuteTypedList<T>(). This will match the columns returned from your query to properties of type T with the same name and give you List<T>.