I am using <PropertyGroup><XsdCodeGenEnabled>true</XsdCodeGenEnabled></PropertyGroup> in my .csproj project file to generate C# classes for the XML schema defined in an .xsd file in the project.
I can see that this generates classes in a namespace called ContractTypes by default, and this works because a .targets file in the XsdCodeGen target is setting the value of the XsdCodeGenNamespaceMappings property as <XsdCodeGenNamespaceMappings>*, ContractTypes</XsdCodeGenNamespaceMappings> and I can set the property the same way but substitute a namespace I want for 'ContractTypes'
The problem I have is that I want to generate C# types from multiple .xsd files in separate namespaces. I am guessing that XsdCodeGenNamespaceMappings is intended to solve this problem, I can see that it is used to build a Dictionary which somehow looks up what output namespace to use. And I don't understand what (in the .xsd file) the input namespace is coming from. ('*' is a magic value.)
How does the XsdTypeImporterTask which does the work actually process the 'NamespaceMappings' parameter?
I've done some diving in the assembly and it looks to me like for XmlSerializer mode the only 'input namespace' value supported by XsdBuildTask is *. And the only way a namespace mapping dictionary with other values is ever used by the build task is if you're in the DataContractSerializer mode. I would be happy to hear I'm wrong however...
Related
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>
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
I have a problem with code generation using xsd.exe (the one provided with the .NET SDK) and also with Xsd2Code (http://xsd2code.codeplex.com/).
I have the following setup of XSD files:
Common.xsd
Summary.xsd
Detail.xsd
Common defines some types that are used in both Summary and Detail and are therefore both Summary and Detail include the line <xs:include schemaLocation="Common.xsd" />.
Now the problem with all XSD code generation tools I tried is that they only take a XSD file with a top level type (so Summary/Detail) and create classes in ONE namespace.
The problem with this is that if I use these tools I get 2 exact copies of every type in Common.xsd (Namespace.Summary.CommonType and Namespace.Detail.CommonType). When I want to use them in code I always have to convert between them (basically just copy all the values) with is quite a nuisance and leads to quite a lot of overhead and confusion.
Is there any XSD code generation tool that handles includes better (ie. puts included types into an own namespace and only generates them once)?
You should try to list all the XSD files in the command line, it should fix your problem for all but some scenarios that hopefully don't apply to your case.
Please take a look at this post, also on SO, it shows exactly what you need to do.
Xsd2Code handles this scenario, you just need to run multiple passes of the command for each xsd file, specifying the namespace..
xsd2code Common.xsd MyNamespace MyNamespace\Common.cs
xsd2code Summary.xsd MyNamespace MyNamespace\Summary.cs /eit+
xsd2code Detail.xsd MyNamespace MyNamespace\Detail.cs /eit+
Each xsd file will be generated into its own source code file (optionally in different namespaces). The /eit+ switch indicates that xsd2code wont generate the included schema types into that file.
The following method in Xsd2Code always returns true:
Xsd2Code.Library.Extensions.CodeExtension.ContainsTypeName(XmlSchema schema, CodeTypeDeclaration type)
This prevents the exclusion of included xml schema items.
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.
If you add a directory in your Visual Studio project and you add a class inside it, the namespace will respect the whole path the directory inclusive.
But sometimes, I prefer having the class in the main project namespace, although it lies in a directory structure, just because I don't want to have mess in my code.
So often happens that I rewrite the Myproject.MyDirectory namespace to be Myproject only.
Is it OK in your opinion? Or does any convention say that every class inside the directory must have it included in the namespace ?
Thanks
There isn't any convention restricting from what you're trying to do. I usually have multiple directories in my project to organize class files and use different namespaces with no respect to the directory structure and I don't have any problems.
In my view, folders and namespaces serve for different purposes.
Folders are useful to provide a clear hierarchy for people who read your code
Namespaces are useful to provide a clear hierarchy for people who use your code. E.g. calling the API provided by your code, when they don't see the actual source code.
Therefore, inconsistency is perfectly fine, as long as each makes sense.
There is no constraint, but some think it's useful to have the namespace identical to the path. So you could choose any namespace and place the class file wherever you want.