I have an program that loads a DLL and instantiates a pre-defined object. This object has a number of properties whose names are defined in an XML file. My program need to get/set these properties within the instantiated object.
I am looking for patterns/methods to do the same.
I cannot use Reflection because this Get/Set methods are called continuously in a loop in my program. Using reflection is very costly.
Do any of you guys have any best practices that you use for such scenarios??
Note : If required, I can change the structure of the object that is dynamically loaded from the DLL (I am developing it) but my program doesn't know the names of the properties of the object (The DLL is also being generated dynamically, so essentially, the user specifies the members required in the object and another program generates the code files and compiles them into the above mentioned DLL. After this, my program loads this newly generated DLL and starts it's work. So, I can change the structure of the object in the DLL but I do not know before-hand the properties contained in the DLL object.)
If it's not too late already, I will suggest the following approach.
Design your external program so that,
It structures the user input as an xml file.
Generates xsd files via Xsd.exe tool which is shipped with .Net Framework SDK
Generates classes from the xsd files again using xsd.exe
This way you can have your main application, deserializing pure xml to classes generated by your external program. In the end it should look like the following and have little code to mantain.
External Program: Xml Data -> Xsl Schema -> GeneratedClasses
Main Application: Xml Data -> Deserialize to Instance
Related
I have a solution with two projects; an asp.net MVC application, and a class library. Let's call them project MVC and project CLS.
In the project CLS, there are two different versions (V1 and V2) of an XSD file that I have used to create two serializable classes with the same name, but under different namespaces (V1 and V2) using xsd2code.
In the MVC project, when the user uploads an XML file, the CLS.dll is used to deserialize the XML into an object. When the XML file is of type V1, the deserialization is very fast, but the XSD file for the V2 version is a lot more complex, and the deserialization can take up to a couple of minutes, only the first time (it's very fast afterwards, until the application is run again).
I used the Sgen.exe tool to create a serializer assembly (CLS.XmlSerializers.dll) for the CLS.V2 type in order to eliminate the first-time creation of the assembly on the fly, and therefore improving the performance.
I have successfully managed to add the Sgen Task to the Post Build events, and the assembly CLS.XmlSerializers.dll is created every time I build the project. Also, I have used the unit test code in this post to make sure the assembly is loaded, and it does. The test passes susscessfully.
However, still, the first time the XML file is deserialized, it takes a long time. So, something still should be wrong. But, I don't know what. Please help.
UPDATE:
I used Fuslogvw.exe as was suggested in the comments, and I can see that the CLS.XmlSerializers.dll is being loaded successfully. Then, how come the first time the XML file is deserialized it takes around one minute, but every time after that takes less than a second?
UPDATE 2:
One of the differences between the two XSD files is that the second one (V2) has a reference to a very big XSD file that containes definitions of some xs:enumeration types that are used in the main file. And, that's the reason the deserialization took a long time. Since all I need to do is to deserialize the XML files into objects and do not need to validate the values of the attributes and elements against those enumerations, I ended up removing the reference to that XSD file, and replacing all the enumeration types with their base types (in this case, xs:string). Now, V2 is deserialized as fast as V1, and I don't even need to use Sgen.exe. I guess Sgen.exe only helps in situations where you need to deserialize a very large XML file. In my case, the XML files are always very small, but the desrialization is (was) complex.
In order to increase performance of XML serialization, assemblies are dynamically generated each time XmlSerializer is instantiated for the first time for a specific type. It happens only once in the application lifetime, but that makes its first usage slow.
When you instantiate an XmlSerializer you have to pass the Type of the objects that you will attempt to serialize and deserialize with that serializer instance. The serializer examines all public fields and properties of the Type to learn about which types an instance references at runtime. It then proceeds to create C# code for a set of classes to handle serialization and deserialization using the classes in the System.CodeDOM namespace. During this process, the XmlSerializer checks the reflected type for XML serialization attributes to customize the created classes to the XML format definition. These classes are then compiled into a temporary assembly and called by the Serialize() and Deserialize() methods to perform the XML to object conversions.
Full Content: Troubleshooting Common Problems with the XmlSerializer
More Info: XmlSerializer Constructor Performance Issues
It is a known issue of x64 jit compiler, it can be very slow in some cases. That's why you have much better performance when running the deserializtion the second time when code is already compiled.
Try to use .net 4.6 or higher, it features a new version of x64 jit compiler (RyuJIT). If it is not possible to update .net version then take a look at this thread.
I am working on a project that consumes (external) services.
The vendor has provided a whole heap of XSDs (89 of them) and I want the convert them all into .Net (C#) classes / class library.
I am using the XSD utility on these but as there is a lot of cross-referencing and importing, they are failing with error messages saying type 'xxxxx' not declared
Now, based my my googling, this is quite simply overcome by compiling the complete reference "tree" but ....
I have 89 files to convert
It concatenates all the schema names together for the output .cs file name (and breaks due to being too long (> 260char))
I thought about creating a class library assembly, starting with the base level schemas (ones without imports) and then telling XSD to convert a schema but use any referenced types from this assembly... but I am not sure how or even if it is possible.
So, how can I best do this please... any advice is welcome..
And yes, 89 schemas are a lot and unfortunately, I have no control on this, I just have to suck it up and deal with it.
You can use /P[arameters]:file.xml option in xsd.exe to specify many parameters in separate file instead of pass them in command line.
Sample of this xml:
<xsd xmlns='http://microsoft.com/dotnet/tools/xsd/'>
<generateClasses language='CS' namespace='MyNamespace'>
<schema>FirstSchema.xsd</schema>
<schema>SecondSchema.xsd</schema>
<schema>ThirdSchema.xsd</schema>
</generateClasses>
</xsd>
Looking for some advice on a tool that I am attempting to create, as I have little to no knowledge on XML.
The scenario is that I have an XSD schema; I have generated a C# class using the XSD tool in the Visual studio command line.
I have then created a basic console app, which will populate the first partial class in the generated C# class.
The program will then serialize this data and create an XML in a folder as a proof of concept.
The issue I’m having is working out the best way to populate and serialize all the data from the class, as the XSD it was generated from is quite large.
Any advice on the best way to handle this would be appreciated!
Use reflection to iterate over the members of your class and populate them with default values depending on the type of the members.
Then serialize and hope like hell that your XML will validate against the schema.
The reason I say this is that inferring .cs from XSD is not an exact science, in that it doesn't guarantee that the XML thus produced by serialization will comply.
So, I'm trying to take an .xsd file (musicxml fixed standard), create an object class, use portions of it - specificially the note object - include it in a graph object, and then save both the graph object and a musicxml validated file.
All in all, the solutions I'm using have one or two massively breaking shortcomings.
Xsd2Code - Creates the file; but for some reason it makes a Items collection (of the type I need, ObservableCollection), and then an enumerable ItemsChoiceType[0-9] ObservableCollection. The problem with the enumerable is after it generates, I have to either have to switch the latter to an Array, or do mumbo-jumbo for the XmlSerialisation attrs. Generates a 2mb .cs file, so alot of code that would be autogenerated and would have to have a crapton of .extend.cs files to get it to fit. Maybe I have to change some switches for it to work? What switches fix this?
LinqToXsd / OpenLinqToXsd - Generates the file, hard codes it to reference a DLL file, then forces you to use List (no option to go to ObservableCollection), which doesn't have EditItem and can't be used for binding to WPF/XAML. Otherwise, a bunch more .extend.cs files.
Altova C# generator - Expensive, requires a bunch of their DLLs to include in the project, messy.
Long story short, has anyone used any of these systems successfully and what did you have to do to shoehorn them? What kind of pain will I have to deal with beyond the issues I'm having
I remember now for XSD.exe: XSD notation doesn't export, individual classes (such as 'note') don't serialise out to xml. I would have to write out the entire thing from scorepartwise to every piece inbetween. Which means I can't serialise a graph object that has 'note's as vertices.
OK, so this is not the most useful question since I can't remember the feature in .net that does this. Basically, that's what I'm asking; what feature is this?
A year or so ago, I was working on a project and we used configuration files that mapped directly to a class using the specific attributes on the class members. This is not the standard app.config, but assemblyname.dll.xml instead.
Perhaps it's a feature within the unity framework? Just a stab in the dark.
It is not critical I figure this out today, but it is just weighing on my brain and annoys me that i can't remember!
thanks!
It's not the standard XML config, but it is built into .NET. Basically, XML serialization allows you to project an XML document from a hydrated class instance, that will map 1:1 to the class it came from and can be used to re-hydrate a new instance of that class.
This can, in the majority of cases, be done without much effort on your part. All that's usually necessary for XML serialization to work is that the object must have a public default constructor, and that all the state information you want to serialize must be public and read-write. In a few cases, some attributes are necessary to define certain behaviors, like derived classes in arrays of their parent class, and defining non-default names for field and property element tags.
One of the major uses of this is for custom configuration files as you stated; you can load the configuration from a persistent state by simply deserializing the file into an instance of the configuration object.
Article: MSDN How To Serialize an Object
This isn't part of the .Net bcl or Unity as far as I am aware. Perhaps it's some other third party or open source component? That being said, it wouldn't be too difficult to build something like this on your own using XmlSerialization.
.net allows for multi layered configuration.
Every machine has the machine.config file. each application has the app.config file (which gets renamed to applicationname.exe.config upon building), but each dll can also have it's own config file. so, if I have the following binaries in my executable folder:
flexitris.exe
flexitrisHelpers.dll
thirdPartyContent.dll
each of them can have their own config file:
flexitris.exe.config
flexitrisHelpers.dll.config
thirdPartyContent.dll.config
and all of them will be read at runtime and accessible using the normal System.Configuration namespace.