|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionMany developers have found the magic of emitting code at runtime using The IL is a great language. However, there are several problems with emitting IL instructions directly. One of them is that it's quite hard to see the actual structure of the generated code, by just looking at series of Using the CodeThere is very little you need to know before you start emitting your next great assembly. Here are the simple steps to your first Hello World generated at runtime: 1. Create an AssemblyAssemblyGen ag = new AssemblyGen("HelloWorld.exe");
This call simply creates an 2. Define Your First ClassTypeGen MyClass = ag.Public.Class("MyClass");
{
// we'll continue here
}
As you can see, this is very similar to what you would write in C#, e.g.: public class MyClass
{
// we'll continue here
}
You can also use other modifiers for the class, such as 3. Define the Main() MethodCodeGen g = MyClass.Public.Static.Method(
typeof(void), "Main", typeof(string[]));
{
Operand args = g.Arg(0, "args");
// we'll continue here
}
The above corresponds to the following in C#: public static void Main(string[] args)
{
// we'll continue here
}
Note the definition of the 4. Write the Body of the Methodg.If(args.ArrayLength() > 0);
{
g.WriteLine("Hello " + args[0] + "!");
}
g.Else();
{
g.WriteLine("Hello World!");
}
g.End();
And compare this to the C# version: if (args.Length > 0)
{
Console.WriteLine("Hello " + args[0] + "!");
}
else
{
Console.WriteLine("Hello World!");
}
As you can see, the code is quite similar. There are some things to note - the g.Invoke(typeof(Console), "WriteLine", ...)
you can use to call any method on any type/instance. Also, you can see the length of the arguments is retrieved by calling 5. Using the Generated CodeNow that we have created a simple hello world application, you can, for example, choose to save it and run it: // this will save the generated assembly
// to the file provided at construction time
ag.Save();
// execute the generated assembly
AppDomain.CurrentDomain.ExecuteAssembly(
"HelloWorld.exe", null, new string[] { "John" });
Or, you can just decide to complete the assembly by calling Other Mini-SamplesIn the hello world sample, only the simplest concepts were shown. You can do, of course, much more with 1. Local VariablesC#int x = 3;
long y = x + 15;
string s;
RunSharpOperand x = g.Local(3);
Operand y = g.Local(typeof(long), x + 15);
Operand z = g.Local(typeof(string));
Note that if the type of the variable is not specified, it automatically takes the type of the initialized expression. Also, an untyped and uninitialized variable can be created by calling Note that it's possible to write code such as: Operand x = g.Local(3);
Operand y = x + 40;
However, the 2. StatementsStatements are always generated using the members of the 2.1 Assignment, Increment/DecrementC#a = 3;
b = a + 5;
c += 4;
b++;
RunSharpg.Assign(a, 3);
g.Assign(b, a + 5);
g.AssignAdd(c, 4);
g.Increment(b);
Note that the assignment operator cannot be overridden in C#. That's why we need a dedicated method to perform the assignment. Also, there is a method for each compound assignment operator. 2.2. Method InvocationC#// instance method
o.SomeMethod(arg1, arg2);
// static method of a system type
Console.WriteLine(arg1, arg2);
// static method of a custom type
MyType.MyMethod(arg1, arg2);
// delegate
d(arg1, arg2);
RunSharp// instance method
g.Invoke(o, "SomeMethod", arg1, arg2);
// static method of a system type
g.Invoke(typeof(Console), "WriteLine", arg1, arg2);
// static method of a custom type
g.Invoke(MyType, "MyMethod", arg1, arg2);
// delegate
g.InvokeDelegate(d, arg1, arg2);
Note that when invoking a method on a generated type, the 3. ExpressionsAs already mentioned, the 3.1 Pre/Post-Fix OperatorsC#x = a++;
y = --b;
RunSharpg.Assign(x, a.PostIncrement());
g.Assign(y, b.PreDecrement());
3.2 Conditional Operator (?:)C#x = a > 0 ? b : c;
RunSharpg.Assign(x, (a > 0).Conditional(b, c));
You should never use the 3.3. Member AccessC#// instance member access
x = o.MyMethod(arg1, arg2);
y = o.MyProperty;
o.MyProperty = z;
f = o.myField;
// static member access
x = MyType.MyMethod(arg1, arg2);
y = Console.BackgroundColor;
RunSharp// instance member access
g.Assign(x, o.Invoke("MyMethod", arg1, arg2));
g.Assign(y, o.Property("MyProperty"));
g.Assign(o.Property("MyProperty"), z);
g.Assign(f, o.Field("myField"));
// static member access
g.Assign(x, Static.Invoke(MyType, "MyMethod", arg1, arg2);
g.Assign(y, Static.Property(typeof(Console), "BackgroundColor");
3.4. Object CreationC#// instance creation
MyType x = new MyType(arg1, arg2);
// array creation
string x = new string[10, 20];
// initialized array creation
int[] x = { 1, 2, 3, 4 };
// delegate creation
MyDelegate x = new MyDelegate(this.MyMethod);
RunSharp// instance creation
Operand x = g.Local(Exp.New(MyType, arg1, arg2));
// array creation
Operand x = g.Local(Exp.NewArray(typeof(string), 10, 20));
// initialized array creation
Operand x = g.Local(Exp.NewInitializedArray(typeof(int), 1, 2, 3, 4));
// delegate creation
Operand x = g.Local(Exp.NewDelegate(MyDelegate, g.This(), "MyMethod"));
Contact MeFor any questions, ideas, suggestions, etc., don't hesitate to contact me, for example through the Happy History
|
||||||||||||||||||||||