This document gives a general outline of XCG, the applications it has, and a brief introduction into how to use it.
XCG is a technology that allows you to create classes using an xml syntax. You can declaratively specify a class' members and their initial values, as well as a number of additional things that make certain common programming tasks easier.
Above all else, XCG is designed to be flexible. This means that everything it does is customisable. XCG stands as a framework around which you can build your own code-generation system. Basically, this means that if XCG does not do what you want, you can make it do what you want. Virtually any part of programming you find tedious can be automated by XCG, and instead of having to build your own code generation system from scratch, you can hook into XCG, which also has the added benefit that your extensions can cooperate with XCG's intrinsic functionality as well as with other extensions written by you or others. Of course you don't have to learn how to write extensions if you just want to use XCG; you can use XCG and any existing extensions without even knowing how the extension system works.
Although XCG and similar systems are ideal for situations where you are designing a graphical UI, it should be remarked that XCG is not limited to this. It is a general purpose method for hooking up .Net objects.
Rather than trying to tell you what XCG is, it would be far simpler to give examples of what it can do. All code examples, unless otherwise specified, use C# and Visual Basic .Net syntax. Even if you're not familiar with C# per se this should make the samples reasonably straight-forward to follow if you're familiar with C++ or Java.
Show examples in Visual Basic .Net
Imagine you have the following code:
struct Address { public string Street; public string Zip; public string City; public string Country; } class Customer { private string _name; private Address _addr; }
Instead of the above definition of the class Customer, you would write the following using XCG:
<gen:CodeFile xmlns:gen="http://www.liacs.nl/~sgroot/xcg/generators.xsd"> <gen:Import>System</gen:Import> <gen:Class name="Customer"> <String gen:name="_name" /> <Address gen:name="_addr" /> </gen:Class> </gen:CodeFile>
(Note: the gen:CodeFile generator is required as the root element of all XCG files, but for brevity is omitted in the examples below, as well as the gen:Import generator which is needed to get access to the System.String class).
At this point, you'll probably remark that that's not really any easier or faster to do than writing the code by hand, and you'd be right. For such trivial cases there is not much benefit from using XCG. It already gets a little more interesting if you want to set some default values, which you'd normally do in a constructor:
class Customer { private string _name; private Address _addr; public Customer() { _name = "John Doe"; _addr.City = "Leiden"; _addr.Country = "the Netherlands"; } }
In XCG, this would become:
<gen:Class name="Customer"> <String gen:name="_name" >John Doe</String <Address gen:name="_addr" City="Leiden" Country="the Netherlands" /> </gen:Class>
As you can see, now we're starting to be more economic. Of course, since this class only has private members, it isn't very useful. You'd normally add accessors (in the form of properties) to get at those private fields.
class Customer { private string _name; private Address _addr; public Customer() { _addr.City = "Leiden"; _addr.Country = "the Netherlands"; } public string Name { get { return _name; } set { _name = value; } } public Address Addr { get { return _addr; } } }
In XCG you'd do it like this:
<gen:Class> <gen:Property name="Name" field="_name" type="String" /> <gen:Property name="Addr" readOnly="true"> <Address gen:name="_addr" City="Leiden" Country="the Netherlands" /> </gen:Property> </gen:Class>
This particular example shows a few things. It shows how the Property generator can be used by itself to generate both a property and its private field, but also how the Property generator can use what is generated by the element it contains. This interaction between generators and their children is one of the fundamental principles in XCG. Almost every element can interact with its children. If you want to write extensions, you'll also find it's important to play nice with your children.
Of course, setting default values is not always very useful. Maybe you want a constructor parameter and use that to initialize the values:
class Customer { private string _name; private int _age; private Address _addr; public Customer(string name, int age, string city) { _name = name; _age = age; _addr.City = city; _addr.Country = "The Netherlands"; } /* Properties omitted */ }
Which is also easily facilitated by XCG:
<gen:Class name="Customer"> <gen:Property name="Name"> <String gen:name="_name">{@name}</String> </gen:Property> <gen:Property name="Age"> <Int32 gen:name="_age">{@age}</Int32> </gen:Property> <gen:Property name="Address" readOnly="true"> <Address gen:name="_addr" City="{@city}" Country="the Netherlands" /> </gen:Property> </gen:Class>
And there's more! You can use XCG to hook up event handlers, you can call constructors on the classes you use, you can inherit from existing classes, you can easily add items to collection types, and, especially with the help of extensions, even much much more. For a more complete overview on the built-in abilities of XCG, we encourage you to read the reference documentation.
And at every step, XCG is designed to make it easy for you to override and extend XCG generated code with your own hand-crafted code. Simply inherit from the XCG generated class, and you can customise the generated code with anything that is best left done manually.
Now that you've gotten a taste of what XCG is, you could try just experimenting a little, but it is recommended you at least explore one further detail about how XCG works, namely Generators and generating elements. After that, you can read the reference documentation, and if you plan to write extensions, the documentation on the working of the XCG engine and the introduction to writing extensions.