I have an XSD schema that has been given to us by a data provider. I cannot modify it. I generated the classes using the XSD.exe command line tool. For everything it works perfectly, I can create my objects in C#, serialize it in XML and validate it against the XSD.
I have a problem with a small portion of it. The expected output is:
<Physical>
<Class>P</Class>
<Capacity>14</Capacity>
<Class>J</Class>
<Capacity>64</Capacity>
<Class>W</Class>
<Capacity>1</Capacity>
<Class>Y</Class>
<Capacity>2</Capacity>
</Physical>
<Saleable Protected="true">
<Class>P</Class>
<Capacity>14</Capacity>
<Class>J</Class>
<Capacity>64</Capacity>
<Class>W</Class>
<Capacity>1</Capacity>
<Class>Y</Class>
<Capacity>2</Capacity>
</Saleable>
As you can see, the child elements of Physical and Sealable alternate (i.e. Class, then Capacity, then Class, then Capacity, etc.).
This is the code of the class that was generated by XSD.exe:
public partial class ClassA
{
private string[] classField;
private Integerctype[] capacityField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("Class", DataType = "token")]
public string[] Class
{
get
{
return this.classField;
}
set
{
this.classField = value;
}
}
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("Capacity", IsNullable = true)]
public Integerctype[] Capacity
{
get
{
return this.capacityField;
}
set
{
this.capacityField = value;
}
}
}
And the output I receive after the serialization:
<Physical>
<Class>P</Class>
<Class>J</Class>
<Class>W</Class>
<Class>Y</Class>
<Capacity>14</Capacity>
<Capacity>64</Capacity>
<Capacity>1</Capacity>
<Capacity>2</Capacity>
</Physical>
<Saleable>
<Class>P</Class>
<Class>J</Class>
<Class>W</Class>
<Class>Y</Class>
<Capacity>14</Capacity>
<Capacity>64</Capacity>
<Capacity>1</Capacity>
<Capacity>2</Capacity>
</Saleable>
As you can see, we lost the alternation between Class and Capacity...
I tried to use the Order property of the XmlElementAttribute: the Class property was decorated with Order = 1, and the Capacity property was decorated with Order = 2, but it did not help. Example:
[System.Xml.Serialization.XmlElementAttribute("Class", DataType = "token", Order = 1)]
public string[] Class
During the validation, with or without the Order property, I receive errors as follow:
The element 'Physical' in namespace 'xxx' has invalid child element
'Class' in namespace 'xxx'. List of possible elements expected:
'Capacity' in namespace 'xxx'.
Finally, here is the portion of the XSD:
<xsd:element name="ClassA" minOccurs="0">
<xsd:complexType>
<xsd:all>
<xsd:element name="Physical" minOccurs="0">
<xsd:annotation>
<xsd:documentation>True, physical class A configuration</xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence minOccurs="0" maxOccurs="unbounded">
<xsd:element name="Class" type="CabinClass.type" />
<xsd:element name="Capacity" type="Integer.ctype" nillable="true" />
</xsd:sequence>
<xsd:attributeGroup ref="Array.attgroup" />
</xsd:complexType>
</xsd:element>
<xsd:element name="Saleable" minOccurs="0">
<xsd:annotation>
<xsd:documentation>Class A configuration for sales purposes</xsd:documentation>
</xsd:annotation>
<xsd:complexType>
<xsd:sequence minOccurs="0" maxOccurs="unbounded">
<xsd:element name="Class" type="CabinClass.type" />
<xsd:element name="Capacity" type="Integer.ctype" nillable="true" />
</xsd:sequence>
<xsd:attributeGroup ref="Array.attgroup" />
</xsd:complexType>
</xsd:element>
</xsd:all>
<xsd:attributeGroup ref="Container.attgroup" />
</xsd:complexType>
</xsd:element>
My guess is that it is related to the presence of xsd:sequence. But as I said, I do not want to modify the XSD as it is provided by a data provider and we must ensure that the XML we generate is fully compatible.
Any idea how can I solve this problem?
Simplified code could be this:
public class Physical
{
[XmlElement("Capacity", typeof(int))]
[XmlElement("Class", typeof(string))]
public object[] Items { get; set; }
}
This will ensure correct deserialization and give the serialization of the elements in the order in which they are placed in the array.
A working version might look like this:
public class Physical
{
[EditorBrowsable(EditorBrowsableState.Never)]
[XmlElement("Capacity", typeof(int))]
[XmlElement("Class", typeof(string))]
public object[] Items
{
get
{
object[] items = new object[Class.Length * 2];
for (int i = 0; i < items.Length; i += 2)
{
items[i] = Class[i / 2];
items[i + 1] = Capacity[i / 2];
}
return items;
}
set
{
Class = new string[value.Length / 2];
Capacity = new int[value.Length / 2];
for (int i = 0; i < value.Length; i += 2)
{
Class[i / 2] = (string)value[i];
Capacity[i / 2] = (int)value[i + 1];
}
}
}
[XmlIgnore]
public string[] Class { get; set; }
[XmlIgnore]
public int[] Capacity { get; set; }
}
Change int to Integerctype, add DataType parameter.
Similarly, change the second class.
Related
I need to validate some generic sensor input. The requirement is, that the validation cannot happen in my code but with a external validator like xsd from outside the codebase to give users the ability to swap the validation logic without needing to code or recompile the application.
I know that the sensor input is only valid for one specific case and therefore would like to generate the xsd from an Instance of a class, that exists at runtime, that was user validated, to get the valid restrictions.
I tried the Idea from this question, however this only works on types and not on instances of classes.
Therefore my question: Is there a way to take a runtime instance of a C# class and convert it to an xsd that has the values of the properties as the only valid restrictions?
Update:
to clarify: What I have is a class like this:
public sealed class Sensor
{
public int Data { get; set; }
public int otherData { get; set; }
public int MoreData { get; set; }
}
the class gets instanciated somewhere (e.g. like this):
var se = new Sensor()
{
Data = 5,
otherData = 10,
MoreData = 15
};
When I now try to create an xsd using something like the following function:
var schemas = new XmlSchemas();
var exporter = new XmlSchemaExporter(schemas);
var mapping = new XmlReflectionImporter().ImportTypeMapping(typeof(Person));
exporter.ExportTypeMapping(mapping);
var schemaWriter = new StringWriter();
foreach (XmlSchema schema in schemas)
{
schema.Write(schemaWriter);
}
return schemaWriter.ToString();
I receive some xsd like this:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="sensor">
<xs:complexType>
<xs:sequence>
<xs:element name="Data" type="xs:integer" />
<xs:element name="otherData" type="xs:integer" />
<xs:element name="moreData" type="xs:integer" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
However this is far from what I want to archieve. I would like to have the proper restrictions built into it (it should look something like this):
<?xml version="1.0" encoding="utf-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="sensor">
<xs:complexType>
<xs:sequence>
<xs:element name="Data">
<xs:simpleType>
<xs:restriction base="xs:integer">
<xs:enumeration value="5"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="otherData">
<xs:simpleType>
<xs:restriction base="xs:integer">
<xs:enumeration value="10"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="moreData">
<xs:simpleType>
<xs:restriction base="xs:integer">
<xs:enumeration value="15"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
I could obviously go ahead load the generated file into memory, strip some attributes and change how the xsd should look like, but this feels wrong because of the following things:
By me defining Rules to how the xsd should look like I take away
flexibility that I would like to have.
This approach seems quite errorprone to me because it seems like basically a little better than direct string manipulation.
This extra code would make my already large code way complexer and harder to understand.
To sum up: I need either a library or a really clever function that can create a xsd like the one above based on the runitme info I have on the class without writing a lot of things to manipulate the xml directly to avoid errorprone or wrong assumptions about the future usage of the validation.
I took your generate schema and added details using Xml Linq. See code below
using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;
using System.Xml.Schema;
using System.IO;
namespace ConsoleApplication131
{
class Program
{
const string FILENAME = #"c:\temp\test.xml";
static void Main(string[] args)
{
Sensor se = new Sensor()
{
Data = 5,
otherData = 10,
MoreData = 15
};
XmlSchemas schemas = new XmlSchemas();
XmlSchemaExporter exporter = new XmlSchemaExporter(schemas);
XmlTypeMapping mapping = new XmlReflectionImporter().ImportTypeMapping(typeof(Sensor));
exporter.ExportTypeMapping(mapping);
StringWriter schemaWriter = new StringWriter();
foreach (XmlSchema schema in schemas)
{
schema.Write(schemaWriter);
}
XDocument doc = XDocument.Parse(schemaWriter.ToString());
XElement root = doc.Root;
XNamespace xs = root.GetNamespaceOfPrefix("xs");
foreach (XElement _class in doc.Descendants(xs + "complexType"))
{
List<XElement> elements = _class.Descendants(xs + "element").ToList();
if (elements.Count > 0)
{
XElement complexType = new XElement(xs + "complexType");
_class.Add(complexType);
XElement sequence = new XElement(xs + "sequence");
complexType.Add(sequence);
foreach (var prop in se.GetType().GetProperties())
{
string name = prop.Name;
string value = prop.GetValue(se, null).ToString();
XElement element = elements.Where(x => (string)x.Attribute("name") == name).FirstOrDefault();
string strType = (string)element.Attribute("type");
XElement newElement = new XElement(xs + "simpleType", new object[] {
new XElement(xs + "restriction", new object[] {
new XAttribute("base", strType),
new XElement(xs + "enumeration", new XAttribute("value", value))
})
});
sequence.Add(newElement);
}
}
}
doc.Save(FILENAME);
}
}
public sealed class Sensor
{
public int Data { get; set; }
public int otherData { get; set; }
public int MoreData { get; set; }
}
}
This question already has answers here:
Calling a function from a string in C#
(5 answers)
Closed 5 years ago.
I am creating a game where you have to code to move a block around the screen in visual studio community 2015. The goal of this project is to create a game to teach people how to code. I have created a method to move the block (just up so far).
private void move(string dir)
{
if(dir=="up"&& pbxBot.Location.Y != 12)
{
this.pbxBot.Top = this.pbxBot.Top - 30;
}
}
I have a textbox(textBox1) and a button (btnGo), I want to set it so when the user types in textBox1 an clicks the go button the code is executed.
For example the user types in "move(up);" in textBox1 and clicks btnGo, the block will move 1 space up(the block is 30x30 pixels hence 30 pixels=1 space)
(This post has been changed so that the text to be compiled is displayed in an editable text box) all that has to be done is create a new Windows form project, and overwrite the project files by using copy and paste from this article into the project files indicated by name)
First things first:
First thing you need to do is load the Roslyn compiler package.
In Visual Studio, Tools/NuGet Package Manager/Package Manager Console
at the PM> prompt, enter Install-Package Microsoft.CodeAnalysis
When you create your project, target .NET Framework 4.6.1 in project/properties/application/Target framework
This code has been tested with Visual Studio 2015 and .NET Framework 4.6.1
Program.cs
using System;
using System.Windows.Forms;
namespace ExecuteText {
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
Form1.cs
using System;
using System.Drawing;
using System.Windows.Forms;
using System.Linq;
using System.IO;
using System.Collections.Generic;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Emit;
using System.Reflection;
namespace ExecuteText
{
/**************************************************************************************************
* A form 1.
*
* #sa System.Windows.Forms.Form
**************************************************************************************************/
public partial class Form1 : Form
{
/**************************************************************************************************
* Default constructor.
**************************************************************************************************/
public Form1()
{
InitializeComponent();
}
/**************************************************************************************************
* Gets the assembly files in this collection.
*
* #param assembly The assembly.
*
* #return An enumerator that allows foreach to be used to process the assembly files in this
* collection.
**************************************************************************************************/
IEnumerable<string> GetAssemblyFiles(Assembly assembly)
{
var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (var assemblyName in assembly.GetReferencedAssemblies())
yield return loadedAssemblies.SingleOrDefault(a => a.FullName == assemblyName.FullName)?.Location;
}
/**************************************************************************************************
* Creates compiler context.
*
* #return The new compiler context.
**************************************************************************************************/
private CSharpCompilation CreateCompilerContext()
{
SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(TextBox.Text);
var assemblyName = Path.GetRandomFileName();
Assembly a = typeof(Form1).Assembly;
var refs = GetMetadataReferencesInAssembly(a);
var compilation = CSharpCompilation.Create(
assemblyName,
new[] {syntaxTree},
refs.ToArray(),
new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
return compilation;
}
/**************************************************************************************************
* Console write errors.
*
* #param result The result.
**************************************************************************************************/
private void ConsoleWriteErrors(EmitResult result)
{
var failures = result.Diagnostics.Where(CodeHasError);
var err = "";
foreach (var diagnostic in failures)
err += $"{diagnostic.Id}: {diagnostic.GetMessage()}";
ErrorTextBox.AppendText(err);
}
/**************************************************************************************************
* Executes the compiled code operation.
*
* #param ms The milliseconds.
**************************************************************************************************/
private void ExecuteCompiledCode(MemoryStream ms)
{
ms.Seek(0, SeekOrigin.Begin);
var assembly = Assembly.Load(ms.ToArray());
var type = assembly.GetType("AStringOfCode.FunctionClass");
var obj = Activator.CreateInstance(type);
type.InvokeMember("Run",
BindingFlags.Default | BindingFlags.InvokeMethod,
null,
obj,
new object[] {Block});
ShowPosition();
}
/**************************************************************************************************
* Gets metadata references in assembly.
*
* #param assembly The assembly.
*
* #return The metadata references in assembly.
**************************************************************************************************/
private List<MetadataReference> GetMetadataReferencesInAssembly(Assembly assembly)
{
var assemblyFiles = GetAssemblyFiles(assembly);
Console.WriteLine(assemblyFiles);
List<MetadataReference> refs = new List<MetadataReference>();
foreach (var assemblyname in assemblyFiles)
refs.Add(MetadataReference.CreateFromFile(assemblyname));
return refs;
}
/**************************************************************************************************
* Code has error.
*
* #param diagnostic The diagnostic.
*
* #return True if it succeeds, false if it fails.
**************************************************************************************************/
private bool CodeHasError(Diagnostic diagnostic)
{
return diagnostic.IsWarningAsError || diagnostic.Severity == DiagnosticSeverity.Error;
}
private void ShowPosition()
{
PositionTextBox.Text = Block.Location.X + "," + Block.Location.Y;
}
private void Form1_Load(object sender, EventArgs e)
{
ShowPosition();
}
private void Run_Click(object sender, EventArgs e)
{
var compilation = CreateCompilerContext();
using (var ms = new MemoryStream())
{
var result = compilation.Emit(ms);
if (result.Success)
{
ExecuteCompiledCode(ms);
}
else
{
ConsoleWriteErrors(result);
}
}
}
private void TextBox_TextChanged(object sender, EventArgs e)
{
}
}
}
Form1.Designer.cs
namespace ExecuteText
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
this.TextBox = new System.Windows.Forms.RichTextBox();
this.Block = new System.Windows.Forms.PictureBox();
this.Run = new System.Windows.Forms.Button();
this.ErrorTextBox = new System.Windows.Forms.RichTextBox();
this.PositionTextBox = new System.Windows.Forms.RichTextBox();
((System.ComponentModel.ISupportInitialize)(this.Block)).BeginInit();
this.SuspendLayout();
//
// TextBox
//
this.TextBox.Location = new System.Drawing.Point(12, 43);
this.TextBox.Name = "TextBox";
this.TextBox.Size = new System.Drawing.Size(400, 605);
this.TextBox.TabIndex = 0;
this.TextBox.Text = resources.GetString("TextBox.Text");
this.TextBox.TextChanged += new System.EventHandler(this.TextBox_TextChanged);
//
// Block
//
this.Block.BackColor = System.Drawing.Color.DodgerBlue;
this.Block.Location = new System.Drawing.Point(591, 314);
this.Block.Name = "Block";
this.Block.Size = new System.Drawing.Size(52, 50);
this.Block.TabIndex = 1;
this.Block.TabStop = false;
//
// Run
//
this.Run.Location = new System.Drawing.Point(12, 12);
this.Run.Name = "Run";
this.Run.Size = new System.Drawing.Size(75, 23);
this.Run.TabIndex = 2;
this.Run.Text = "Run";
this.Run.UseVisualStyleBackColor = true;
this.Run.Click += new System.EventHandler(this.Run_Click);
//
// ErrorTextBox
//
this.ErrorTextBox.Location = new System.Drawing.Point(12, 665);
this.ErrorTextBox.Name = "ErrorTextBox";
this.ErrorTextBox.Size = new System.Drawing.Size(747, 96);
this.ErrorTextBox.TabIndex = 3;
this.ErrorTextBox.Text = "";
//
// PositionTextBox
//
this.PositionTextBox.Location = new System.Drawing.Point(418, 43);
this.PositionTextBox.Name = "PositionTextBox";
this.PositionTextBox.Size = new System.Drawing.Size(341, 44);
this.PositionTextBox.TabIndex = 4;
this.PositionTextBox.Text = "";
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(771, 773);
this.Controls.Add(this.PositionTextBox);
this.Controls.Add(this.ErrorTextBox);
this.Controls.Add(this.Run);
this.Controls.Add(this.Block);
this.Controls.Add(this.TextBox);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
((System.ComponentModel.ISupportInitialize)(this.Block)).EndInit();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.RichTextBox TextBox;
private System.Windows.Forms.Button Run;
public System.Windows.Forms.PictureBox Block;
private System.Windows.Forms.RichTextBox ErrorTextBox;
private System.Windows.Forms.RichTextBox PositionTextBox;
}
}
Form1.resx
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="TextBox.Text" xml:space="preserve">
<value>using System;
using System.Drawing;
using System.Windows.Forms;
namespace AStringOfCode
{
public class FunctionClass
{
enum Directions
{
e_Up,
e_Down,
e_Left,
e_Right
};
private void Move(PictureBox p, Directions direction)
{
var fromPoint = p.Location;
var toPoint = p.Location;
switch (direction)
{
case Directions.e_Up:
toPoint = new Point(fromPoint.X, fromPoint.Y - 1);
break;
case Directions.e_Down:
toPoint = new Point(fromPoint.X, fromPoint.Y + 1);
break;
case Directions.e_Left:
toPoint = new Point(fromPoint.X - 1, fromPoint.Y);
break;
case Directions.e_Right:
toPoint = new Point(fromPoint.X + 1, fromPoint.Y);
break;
}
p.Location = toPoint;
}
public void Run(PictureBox p)
{
Move(p, Directions.e_Up);
}
}
}</value>
</data>
</root>
This should be what you're looking for.
When you run the application, you will see three windows and a button
1. the code window
2. the position window
3. the error window
and the "Run" Button.
...oh yes, let's not forget the "Block" we're moving!
you can modify the call to "move" by changing the second parameter to one of the 4 defined directions. When the "run" button is clicked, the code in the code window will be compiled and run (if there are no errors), the blue block will move one pixel in the direction indicated by the parameter to Move(), and the new position will be displayed in the Position window.
If there are errors in the compilation, they will be displayed in the Error window.
Hope this helps
If you're checking the parameter value in your move function, why not just check for the command itself?
Take the value in the text box and split it by the "(" symbol, then take the first part of your new list, in this case "move" and perform logic according to that value:
switch (textBoxValue.split("(")[0])
{
case "Move":
move();
break;
and so on.
Start by Extracting the method name from the string using string.Split or regex.
Then you can use reflection to invoke the method, something like this:
Type thisType = this.GetType();
MethodInfo theMethod = thisType.GetMethod("MethodName");
theMethod.Invoke(this, parameters, ...);
This requires a using System.Reflection; Reference.
You can get the parameters just by using regex or string.Split to get what's inside the brackets. Chuck it in a try catch statement to handle when the function does not exist.
I wanted to deserialize TCX files containing sport data into some my local/temporary object. I used XSD schema describing such format and created classes using xsd2code.
After that I was able to deserialize XML into proper object and the deserialzator didn't throw any exception. But when I started to expand behaviour of component I noticed that some fields are not properly fullfield.
The problem is about reading the tags Track. Deserialized Lap in substructure shows all data properly, but the Tracks number is displayed as 0.
Is there any way to trigger deserializer to interpret it properly? Did I miss some attribute? Why it is not reading it properly even if there was no exception.
I know, it is hard to explain and put all needed classes into comment - so I share my current status here and just write that: GetUnifiedData_WhenTrackPointsAreGivenInTcx_UnifiedTrackPointShouldRetreiveIt() is not passing and shows my problem.
<Activities>
<Activity Sport="Running">
<Id>2015-01-25T12:14:34Z</Id>
<Lap StartTime="2015-01-25T12:14:34Z">
<TotalTimeSeconds>507.0989990</TotalTimeSeconds>
<DistanceMeters>1000.0000000</DistanceMeters>
<MaximumSpeed>2.5790000</MaximumSpeed>
<Calories>95</Calories>
<AverageHeartRateBpm xsi:type="HeartRateInBeatsPerMinute_t">
<Value>155</Value>
</AverageHeartRateBpm>
<MaximumHeartRateBpm xsi:type="HeartRateInBeatsPerMinute_t">
<Value>173</Value>
</MaximumHeartRateBpm>
<Intensity>Resting</Intensity>
<TriggerMethod>Distance</TriggerMethod>
<Track>
<Trackpoint>
<Time>2015-01-25T12:14:34Z</Time>
<Position>
<LatitudeDegrees>50.8918607</LatitudeDegrees>
<LongitudeDegrees>16.7403161</LongitudeDegrees>
</Position>
<AltitudeMeters>233.1999969</AltitudeMeters>
<DistanceMeters>0.0000000</DistanceMeters>
<HeartRateBpm xsi:type="HeartRateInBeatsPerMinute_t">
<Value>88</Value>
</HeartRateBpm>
<Extensions>
<TPX xmlns="http://www.garmin.com/xmlschemas/ActivityExtension/v2" CadenceSensor="Footpod">
<Speed>0.0000000</Speed>
</TPX>
</Extensions>
</Trackpoint>
</Track>
<Track>
</Track>
<Extensions>
<FatCalories xmlns="http://www.garmin.com/xmlschemas/FatCalories/v1">
<Value>0</Value>
</FatCalories>
<LX xmlns="http://www.garmin.com/xmlschemas/ActivityExtension/v2">
<AvgSpeed>1.9720000</AvgSpeed>
</LX>
</Extensions>
</Lap>
</Activity>
</Activities>
The problem is that your data model is wrong. In the below excerpt, you will see two Track elements below the Lap element:
<?xml version="1.0" encoding="utf-16" standalone="no"?>
<TrainingCenterDatabase xmlns="http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.garmin.com/xmlschemas/ActivityExtension/v2 http://www.garmin.com/xmlschemas/ActivityExtensionv2.xsd http://www.garmin.com/xmlschemas/FatCalories/v1 http://www.garmin.com/xmlschemas/fatcalorieextensionv1.xsd http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2 http://www.garmin.com/xmlschemas/TrainingCenterDatabasev2.xsd">
<Activities>
<Activity Sport="Running">
<Id>2015-01-25T12:14:34Z</Id>
<Lap StartTime="2015-01-25T12:14:34Z">
<Track>
<Trackpoint>
<Time>2015-01-25T12:14:34Z</Time>
... etc etc
</Trackpoint>
<Trackpoint>
... etc etc
</Trackpoint>
</Track>
<Track>
<Trackpoint>
... etc etc
<Trackpoint>
</Track>
However, in your data model Track is a singleton property of Lap containing an array of TrackPoint_t entries. When XmlSerializer encounters more than one Track elements it fails to deserialize them.
Thus your data model needs to be as follows. Introduce an intermediate class Track_t:
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2")]
public class Track_t
{
public Track_t()
{
this.Track = new List<Trackpoint_t>();
}
[System.Xml.Serialization.XmlElement("TrackPoint", typeof(Trackpoint_t), IsNullable = false)]
public List<Trackpoint_t> Track { get; set; }
}
And modify ActivityLap_t as follows:
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.34234")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.garmin.com/xmlschemas/TrainingCenterDatabase/v2")
]
public partial class ActivityLap_t
{
private List<Track_t> _track; // Change type to `Track_t`
public ActivityLap_t()
{
this._extensions = new Extensions_t();
this._track = new List<Track_t>(); // Change type to `Track_t`
this._maximumHeartRateBpm = new HeartRateInBeatsPerMinute_t();
this._averageHeartRateBpm = new HeartRateInBeatsPerMinute_t();
}
// Change type to `Track_t` and change attribute to `XmlElement`
[System.Xml.Serialization.XmlElement("Track", typeof(Track_t), IsNullable = false)]
public List<Track_t> Track
{
get { return this._track; }
set { this._track = value; }
}
// Remainder unchanged.
}
You will also need to modify Course_t in the same way.
The xsd does specify the existence of a type Track_t and that ActivityLap_t can contain an unbounded number of Track elements of this type, so somehow the XSD was transformed into classes incorrectly:
<xsd:complexType name="ActivityLap_t">
<xsd:sequence>
<xsd:element name="TotalTimeSeconds" type="xsd:double" />
<xsd:element name="DistanceMeters" type="xsd:double" />
<xsd:element name="MaximumSpeed" type="xsd:double" minOccurs="0" />
<xsd:element name="Calories" type="xsd:unsignedShort" />
<xsd:element name="AverageHeartRateBpm" type="HeartRateInBeatsPerMinute_t" minOccurs="0" />
<xsd:element name="MaximumHeartRateBpm" type="HeartRateInBeatsPerMinute_t" minOccurs="0" />
<xsd:element name="Intensity" type="Intensity_t" />
<xsd:element name="Cadence" type="CadenceValue_t" minOccurs="0" />
<xsd:element name="TriggerMethod" type="TriggerMethod_t" />
<xsd:element name="Track" type="Track_t" minOccurs="0" maxOccurs="unbounded" /> <!-- Notice that maxOccurs is unbounded so "Track" needs to be a list -->
<xsd:element name="Notes" type="xsd:string" minOccurs="0" />
<xsd:element name="Extensions" type="Extensions_t" minOccurs="0">
<xsd:annotation>
<xsd:documentation>
You can extend Training Center by adding your own elements from another schema here.
</xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
<xsd:attribute name="StartTime" type="xsd:dateTime" use="required" />
</xsd:complexType>
and
<xsd:complexType name="Track_t">
<xsd:sequence>
<xsd:element name="TrackPoint" type="TrackPoint_t" maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType>
I am trying to consume a Java web service but get an exception System.InvalidCastException: Cannot assign object of type ValueArrayType to an object of type ValueArrayType[]
I am consuming a third party service so cannot change the service and have been informed that they can consume the service ok with php and java.
Value Array type is complex type
<xsd:complexType name="ValueArrayType">
<xsd:sequence>
<xsd:element name="ValueName" type="xsd:string"/>
<xsd:element name="ValueType" type="xsd:string"/>
<xsd:element name="ValueValue" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
It is an element in the response DetailsType that can have several occurrences as it has max = unbound and is wrapped by a sequence attribute.
<xsd:complexType name="DetailsType">
<xsd:sequence>
<xsd:element name="Id" type="xsd:int"/>
<xsd:element name="MobileName" type="xsd:string"/>
<xsd:element name="ValueArray" type="tns:ValueArrayType" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
I have tried wsdll.exe and svrcutil.exe to try and generate client code.
the ValueArrayType is defined in the generated code as an array.
public ValueArrayType[] ValueArray
{
get
{
return this.valueArrayField;
}
set
{
this.valueArrayField = value;
}
}
an example of the data coming back is.
....
<Details xsi:type="tns:DetailsType">
<Id xsi:type="xsd:int">9999</Id>
<ValueArray xsi:type="tns:ValueArrayType">
<ValueName xsi:type="xsd:string">Count</ValueName>
<ValueType xsi:type="xsd:string">numeric</ValueType>
<ValueValue xsi:type="xsd:string">11</ValueValue>
</ValueArray>
<ValueArray xsi:type="tns:ValueArrayType">
<ValueName xsi:type="xsd:string">Start</ValueName>
<ValueType xsi:type="xsd:string">numeric</ValueType>
<ValueValue xsi:type="xsd:string">31</ValueValue>
</ValueArray>
<ValueArray xsi:type="tns:ValueArrayType">
<ValueName xsi:type="xsd:string">A1</ValueName>
<ValueType xsi:type="xsd:string">numeric</ValueType>
<ValueValue xsi:type="xsd:string">23</ValueValue>
</ValueArray>
<ValueArray xsi:type="tns:ValueArrayType">
<ValueName xsi:type="xsd:string">A2</ValueName>
<ValueType xsi:type="xsd:string">numeric</ValueType>
<ValueValue xsi:type="xsd:string">0</ValueValue>
</ValueArray>
<ValueArray xsi:type="tns:ValueArrayType">
<ValueName xsi:type="xsd:string">X1</ValueName>
<ValueType xsi:type="xsd:string">numeric</ValueType>
<ValueValue xsi:type="xsd:string">0</ValueValue>
</ValueArray>
.....
If I change the client code to public ValueArrayType ValueArray
instead of an array then the client works but only gets the first ValueArray returned.
Have tried suggestions from http://blogs.msdn.com/b/netcfteam/archive/2007/02/01/why-your-netcf-apps-fail-to-call-some-web-services.aspx.
Update
I have generated a WCF Service with the proxyclass generated from scvutil.
When I consume and check the xml with WCFTestCLient.exe.
An Array type is sent back as
<ValueArray>
<ValueArrayType>
<ValueName>a</ValueName>
<ValueType>string</ValueType>
<ValueValue>1</ValueValue>
</ValueArrayType>
<ValueArrayType>
<ValueName>a</ValueName>
<ValueType>string</ValueType>
<ValueValue>2</ValueValue>
</ValueArrayType>
</ValueArray>
I assume either the data being sent does not match the WSDL or there is a bug in the C# scvutil, or System.ServiceModel.
Try to specify your element type inside the generated code
[XmlElement(ElementName = "ValueArray", Type = typeof(ValueArrayType), Namespace = "YourSchemaNamespace")]
public ValueArrayType[] ValueArray
{
get
{
return this.valueArrayField;
}
set
{
this.valueArrayField = value;
}
}
More information is available at MSDN
The problem is caused by incorrect xsi:type values that mislead WCF deserialization (described here).
The workaround is to use OperationFormatUse.Literal instead of OperationFormatUse.Encoded on all operations.
Can you try something like this ?
JavaServecie js= new JavaService();
js.ValueArrayType arr= js.GetValues(.....
if the class is public.
Good day.
I got a problem about the attribute of "ref" for my XSD file.
My code :
using System;
using System.Collections;
using System.Xml;
using System.Xml.Schema;
class XmlSchemaTraverseExample
{
static void Main()
{
// Add the customer schema to a new XmlSchemaSet and compile it.
// Any schema validation warnings and errors encountered reading or
// compiling the schema are handled by the ValidationEventHandler delegate.
XmlSchemaSet schemaSet = new XmlSchemaSet();
schemaSet.ValidationEventHandler += new ValidationEventHandler(ValidationCallback);
schemaSet.Add("http://www.w3.org/2001/XMLSchema", "recipe.xsd");
schemaSet.Compile();
// Retrieve the compiled XmlSchema object from the XmlSchemaSet
// by iterating over the Schemas property.
XmlSchema customerSchema = null;
foreach (XmlSchema schema in schemaSet.Schemas())
{
customerSchema = schema;
}
// Iterate over each XmlSchemaElement in the Values collection
// of the Elements property.
foreach (XmlSchemaElement element in customerSchema.Elements.Values)
{
Console.WriteLine("Element: {0}", element.Name);
// Get the complex type of the Customer element.
XmlSchemaComplexType complexType = element.ElementSchemaType as XmlSchemaComplexType;
// If the complex type has any attributes, get an enumerator
// and write each attribute name to the console.
if (complexType.AttributeUses.Count > 0)
{
IDictionaryEnumerator enumerator =
complexType.AttributeUses.GetEnumerator();
while (enumerator.MoveNext())
{
XmlSchemaAttribute attribute =
(XmlSchemaAttribute)enumerator.Value;
Console.WriteLine("Attribute: {0}", attribute.Name);
}
}
// Get the sequence particle of the complex type.
XmlSchemaSequence sequence = complexType.ContentTypeParticle as XmlSchemaSequence;
// Iterate over each XmlSchemaElement in the Items collection.
foreach (XmlSchemaElement childElement in sequence.Items)
{
Console.WriteLine("Element: {0}, {1}, {2}", childElement.RefName, childElement.MinOccurs, childElement.MaxOccurs);
}
}
}
static void ValidationCallback(object sender, ValidationEventArgs args)
{
if (args.Severity == XmlSeverityType.Warning)
Console.Write("WARNING: ");
else if (args.Severity == XmlSeverityType.Error)
Console.Write("ERROR: ");
Console.WriteLine(args.Message);
}
}
my XSD file
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="Recipe">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="DocumentInfo" minOccurs="1" maxOccurs="1" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<!-- Element of DocumentInfo -->
<xsd:element name="DocumentInfo">
<xsd:complexType>
<xsd:attribute name="Name" type="xsd:string" />
<xsd:attribute name="Description" type="xsd:string" />
<xsd:attribute name="Creator" type="xsd:string" />
<xsd:attribute name="CreateTime" type="xsd:string" />
<xsd:attribute name="Revisor" type="xsd:string" />
<xsd:attribute name="ReviseTime" type="xsd:string" />
<xsd:attribute name="Version" type="xsd:string" />
<xsd:attribute name="Frozen" type="xsd:boolean" />
<xsd:attribute name="ASCSVersion" type="xsd:string" use="optional"/>
</xsd:complexType>
</xsd:element>
</xsd:schema>
Now when i got the output below:
Element: Recipe
Element: http://www.w3.org/2001/XMLSchema:DocumentInfo, 1, 1
Element: http://www.w3.org/2001/XMLSchema:Prerequisite, 1, 1
Element: http://www.w3.org/2001/XMLSchema:Headers, 0, 1
Element: http://www.w3.org/2001/XMLSchema:Steps, 1, 1
How to remove the prefix of "http://www.w3.org/2001/XMLSchema" ?
I can only take use of the Attribute of "childElement.RefName", I can't find "childElement.Ref".
DEV IDE: VS2005. .NET 2.0.
Thanks in advance here.
BR!
Nano
You can either use childElement.Name or childElement.QualifiedName.Name
XmlSchemaElement.Name
XmlSchemaElement.QualifiedName