This tool help you to work on projects by brainstorming in an XML document then converting into a complete Visual Studio project or C# type.
Create a simple assembly
<Assembly />
While that will create a basic VS2005/C# project, you should alway set the XAG namespace to "x".
<Assembly xmlns:x="http://www.jampad.net/xag/2006/11/" />
To add a reference to the assembly
<Assembly xmlns:x=" http://www.jampad.net/xag/2006/11/">
<References>
<Reference Name="System.Runtime.Serialization" />
</References>
</Assembly>
To create a new folder
<Assembly xmlns:x="http://www.jampad.net/xag/2006/11/">
<Folder Header="My Folder">
</Folder>
</Assembly>
Note that folders can be nested.
<Assembly xmlns:x=" http://www.jampad.net/xag/2006/11/">
<Folder Header="My Folder">
<Folder Header="Sales">
<Folder Header="Data Contracts">
</Folder>
<Folder Header="Processors">
</Folder>
</Folder>
<Folder Header="General">
</Folder>
</Folder>
</Assembly>
To create a simple class
<ClassName x:Key="ClassKey" Type="Class" Namespace="ClassNamespace">
</ClassName>
Creating any type is very similar. You simply change the Type value to create the type of type you want. Possible values include Class, Struct, Interface, Attribute, and Delegate.
In this sample you can also see how to set a type's namespace.
The x:Key attribute is very important and is used for strong-linking within the assembly. The x:Key attribute is discussed a later.
Setting a default namespace
You don't actually have to set the namespace on every single type. If most of your types are in the same namespace, simply set a default namespace at the assembly level.
<Assembly xmlns:x="http://www.jampad.net/xag/2006/11/" DefaultNamespace="GeneralNamespace">
<ClassName x:Key="ClassKey" Type="Class" />
</Assembly>
Namespaces specifically set on a type override the default namespace for that specific type.
To create methods
<ClassName x:Key="ClassKey" Type="Class" Namespace="ClassNamespace">
<Methods>
<Process ReturnType="Void" />
<Parse ReturnType="Int32">
<Parameters>
<Parameter Name="text" Type="String" />
</Parameters>
</Parse>
</Methods>
</ClassName>
To create properties
<ClassName x:Key="ClassKey" Type="Class" Namespace="ClassNamespace">
<Properties>
<Id Type="Int32" />
<Name Type="String" />
</Properties>
</ClassName>
When creating properties, the backing fields are automatically created.
To create private fields
<ClassName x:Key="ClassKey" Type="Class" Namespace="ClassNamespace">
<Fields>
<M Type="Int32" />
<N Type="Int32" />
</Fields>
</ClassName>
To enforce proper design, public fields are NOT possible. Also, they are automatically camelCased. So, in the above example two private Int32 fields are created called m and n.
To create constructors
<ClassName x:Key="ClassKey" Type="Class" Namespace="ClassNamespace">
<Constructors>
<Constructor>
<Id Type="Int32" />
<Name Type="String" />
</Constructor>
</Constructors>
</ClassName>
It's important to remember that, for classes, a parameterless constructor are automatically added.
Enabling autogenerated constructors
To simplify type implemenation, you may set AutoGenerateConstructorsByProperties to true to create the type with a constructor that automatically accepts parameters and saves them to their respective properties.
<ClassName x:Key="ClassKey" Type="Class" AutoGenerateConstructorsByProperties="True" Namespace="ClassNamespace">
<Constructors>
<Constructor>
<Id Type="Int32" />
<Name Type="String" />
</Constructor>
</Constructors>
</ClassName>
In the above case, AutoGenerateConstructorsByProperties="True" automatically generates the following constructor
public ClassName(Int32 id, String name) {
this.Id=id;
this.Name=name;
}
"Constructors" is plural in AutoGenerateConstructorsByProperties to allow for future development of the feature.
Creating a static property, field, or method
<ClassName x:Key="ClassKey" Type="Class" AutoGenerateConstructorsByProperties="True" Namespace="ClassNamespace">
<Properties>
<SharedValue Type="Double" Static="True"/>
<Id Type="Int32" />
<Name Type="String" />
</Properties>
</ClassName>
Even though AutoGenerateConstructorsByProperties is set to True in this example, SharedValue is not set in the constructor. It is completely ignored in that context.
To create a simple struct
<Assembly xmlns:x="http://www.jampad.net/xag/2006/11/">
<Folder Header="My Folder">
<ThreeDPoint x:Key="MyThreeDPointStruct" Type="Struct" Namespace="OxMapperLibrary">
<Fields>
<A Type="Int32" Value="1" />
</Fields>
<Properties>
<B AccessModifier="Public" Type="Int32" />
</Properties>
</ThreeDPoint>
</Folder>
</Assembly>
The rules for structs are much more complicated than the rules for classes and this is compounded further as this system enforces the official framework design guidelines.
Since structs must have their fields initialized before control leaves the constructor, the following also initializes fields.
Also note that fields automatically generated in structs have _ before them. This is usually a poor idea, but since you can't initialize with "this" in a struct, _ is required to differentiate it in constructors.
Next, note that the value of A is completely ignored. You can't have instance initializers in a struct.
Last, note that A is converted to a because it's private. This is to enforce proper programming habits.
In a struct, the only case in which a PascalCased member will not be converted to a camelCased member is when the member is static.
To create a struct with constructors and one or more static properties or fields.
Note that the parameterless constructor is ignored as they are not valid in structs.
<FourDimensionalPoint x:Key="MyThreeDPointStruct" Type="Struct" Namespace="OxMapperLibrary">
<Fields>
<C Type="Int32" Value="0" AccessModifier="true" Static="true" />
<Z Type="Int32" Value="1" />
</Fields>
<Properties>
<X AccessModifier="Public" Type="Int32" />
<Y AccessModifier="Public" Type="Int32" />
</Properties>
<Constructors>
<Constructor>
<Parameter Type="Int32" Name="x" />
<Parameter Type="Int32" Name="y" />
</Constructor>
<Constructor />
</Constructors>
</FourDimensionalPoint>
To create an enumeration
<Assembly xmlns:x="http://www.jampad.net/xag/2006/11/">
<Folder Header="My Folder">
<Gender x:Key="Gender" Type="Enumeration" Namespace="General">
<Fields>
<Male Value="0" />
<Female Value="1" />
</Fields>
</Gender>
</Folder>
</Assembly>
Setting an attribute
<Assembly xmlns:x="http://www.jampad.net/xag/2006/11/">
<Folder Header="My Folder">
<Gender x:Key="Gender" Type="Enumeration" Namespace="General">
<Attributes>
<Attribute Type="Serializable" />
</Attributes>
<Fields>
<Male Value="0" />
<Female Value="1" />
</Fields>
</Gender>
</Folder>
</Assembly>
Set attributes with named and positional parameters
<Attributes>
<Attribute Type="AssemblyTitle" Namespace="System.Reflection">
<Initializer>
<ConstructorParameters>
<ParameterValue Value="OxMapperLibrary" ValueFormat="String">
</ParameterValue>
</ConstructorParameters>
</Initializer>
</Attribute>
<Attribute Type="AssemblyDescription">
<Initializer>
<ConstructorParameters>
<ParameterValue Value="My Description goes here." ValueFormat="String">
</ParameterValue>
</ConstructorParameters>
</Initializer>
</Attribute>
<Attribute Type="ComVisible" Namespace="System.Runtime.InteropServices">
<Initializer>
<ConstructorParameters>
<ParameterValue Value="False" ValueFormat="Literal">
</ParameterValue>
</ConstructorParameters>
</Initializer>
</Attribute>
</Attributes>
To apply this to the AssemblyInfo.cs file, simply put it under the <Assembly /> branch like so.
<Assembly xmlns:x=" http://www.jampad.net/xag/2006/11/">
<Attributes>
</Attributes>
</Assembly>
Create a custom attribute
Note that the word Attribute is automatically appended to the end of the type name. Also note that a custom attribute is really just a class with the AttributeUsage attribute applied to it.
<MyCustom x:Key="MyCustom" AccessModifier="Internal" Type="Attribute" Namespace="ProcessorLibraryMockup.Sales.Attributes">
<Attributes>
<Attribute Type="AttributeUsage" Namespace="System">
<Initializer>
<ConstructorParameters>
<ParameterValue Value="AttributeTargets.All">
</ParameterValue>
</ConstructorParameters>
<NamedParameters>
<ParameterValue Name="Inherited" Value="True">
</ParameterValue>
<ParameterValue Name="AllowMultiple" Value="False">
</ParameterValue>
</NamedParameters>
</Initializer>
</Attribute>
</Attributes>
<Properties>
<Name AccessModifier="Public" Type="String">
</Name>
<Id AccessModifier="Public" Type="Int32">
</Id>
</Properties>
<Constructors>
<Constructor>
<Parameter Type="String" Name="name">
</Parameter>
</Constructor>
</Constructors>
</MyCustom>
Creating a type referencing other types
This is what the x:Key attribute is for. The following example shows a Person class with a DataContract attribute applied as well as an instance of MyCustomAttribute applies as well. The x:Key reference allows for strong-linking between types thereby eliminating the possibility for ambiguitity. Note also that the x:Key reference also brings in any the appropriate namespace if necesary.
<Gender x:Key="Gender" Type="Enumeration" Namespace="General">
<Attributes>
<Attribute Type="Serializable">
</Attribute>
</Attributes>
<Fields>
<Male Value="0" />
<Female Value="1" />
</Fields>
</Gender>
<Person x:Key="Person" Type="Class" AutoGenerateConstructorsByProperties="True" AccessModifier="Public" Namespace=" ProcessorLibraryMockup.Sales">
<Attributes>
<Attribute Type="DataContract" Namespace="System.Runtime.Serialization" />
<Attribute Type="{Type MyCustom}" />
</Attributes>
<Fields>
<Code Type="Int32" Value="7" />
<PublicCode Type="Int32" Value="3" Static="True" />
</Fields>
<Properties>
<Gender Type="{Type Gender}" Value="Male" />
<Name Type="String" Static="True" />
</Properties>
<Methods>
<TryParseId ReturnType="Boolean">
<Parameters>
<Parameter Name="text" Type="String" />
</Parameters>
</TryParseId>
</Methods>
</Person>
Creating aliases
<Cart x:Key="Cart" Type="Class" AccessModifier="Public" Namespace="ProcessorLibraryMockup.Sales">
<Aliases>
<Alias x:Key="LineItemsCollection" Name="Whatever" Type="System.Collections.ObjectModel.Collection[{Type Item}]" />
</Aliases>
<Properties>
<LineItems Type="{Type LineItemsCollection}" />
</Properties>
</Cart>
Using generic types
Generic types are currently only allowed via aliasing. That is, you have to create an alias ("using Name = Type<Generic>;") as seen below.
See above "Creating aliases" example for example.
Creating and implementing custom interfaces
Note that implementing an interface of your own creation is very simple. Simply
write the interface, give it a key, then create the implementing type and implement
the interface.
<IProcessorService x:Key="IProcessorService" Type="Interface" AccessModifier="Public" Namespace="ProcessorLibraryMockup.ServiceContracts">
<Attributes>
<Attribute Type="ServiceContract" Namespace="System.ServiceModel" Reference="System.ServiceModel">
</Attribute>
</Attributes>
<Methods>
<ProcessSale ReturnType="Void">
<Attributes>
<Attribute Type="OperationContract" Namespace="System.ServiceModel" Reference="System.ServiceModel ">
</Attribute>
</Attributes>
<Parameters>
<Parameter Name="sale" Type="{Type Sale}" />
</Parameters>
</ProcessSale>
</Methods>
</IProcessorService>
<ProcessorService Type="Class" AccessModifier="Public" Namespace="ProcessorLibraryMockup.Service ">
<Implements>
<Interface Name="{Type IProcessorService}" Namespace="System" />
</Implements>
</ProcessorService>
The generated type will completely implement the interface and all methods will contain a line which throws an exception so the method will not halt compilation.
Creating a custom delegate
<ProcessorEventArgs x:Key="ProcessorEventArgs" Type="Class" AccessModifier="Public" Inherits="System.EventArgs" Namespace="ProcessorLibraryMockup">
<Properties>
<Text Type="String">
</Text>
</Properties>
<Constructors>
<Constructor>
<Parameter Type="String" Name="text">
</Parameter>
</Constructor>
</Constructors>
</ProcessorEventArgs>
<Write x:Key="Write" AccessModifier="Public" Type="Delegate" ReturnType="Void" Namespace="ProcessorLibraryMockup">
<Parameters>
<Parameter Name="sender" Type="Object">
</Parameter>
<Parameter Name="ea" Type="{Type ProcessorEventArgs}">
</Parameter>
</Parameters>
</Write>
Creating an event
Note that this is simply one line and all it really does it provide a name, an access modifier, and a delegate reference.
<AbstractProcessor x:Key="AbstractProcessor" Type="Class" ExistenceModifier="Abstract" AccessModifier="Public" Namespace="ProcessorLibraryMockup">
<Events>
<Tracer DelegateType="{Type Write}" AccessModifier="Public" />
</Events>
</AbstractProcessor>
Inheriting a type
This is simply a matter of using the Inherits XML attribute. As with all references, the appropriate namespace will be brought in, if needed.
<InheritedConcreteProcessor Type="Class" AccessModifier="Public" Inherits="{Type ConcreteProcessor}" Namespace="ProcessorLibraryMockup">
</InheritedConcreteProcessor>
Using ref and out keywords
When in a type...
<Methods>
<TryParseId ReturnType="Boolean">
<Parameters>
<Parameter Name="text" Type="String" />
<Parameter Name="id" RefOut="Out" Type="Int32" />
</Parameters>
</TryParseId>
</Methods>
"ref" is used via RefOut="Ref"
Inline instantiation of properties
This is done by setting InstantiateObject to true on the property.
<Sale x:Key="Sale" Type="Class" AccessModifier="Public" Namespace="ProcessorLibraryMockup.Sales">
<Properties>
<Person AccessModifier="Public" Type="{Type Person}" InstantiateObject="True">
</Person>
<CreditCard AccessModifier="Public" Type="{Type CreditCard}">
</CreditCard>
</Properties>
<Methods>
<CheckId ReturnType="Boolean">
<Parameters>
<Parameter Name="id" RefOut="Ref" Type="Int32" />
</Parameters>
</CheckId>
</Methods>
</Sale>
Embedded Configuration File
Using XAG, you can include a configuration file literal section which will be converted to an app.config file in your VS2005 project.
<Assembly xmlns:x=" http://www.jampad.net/xag/2006/11/">
<References>
<Reference Name="System.Runtime.Serialization" />
</References>
<Configuration>
<appSettings>
<add key="DocumentLocation" value="C:\Documents"/>
</appSettings>
</Configuration>
</Assembly>