Download presentation
Presentation is loading. Please wait.
Published byJuniper Fields Modified over 9 years ago
1
DEV485.NET CodeDOM demystified Beat Schwegler Architect Evangelist.NET Developer Group Microsoft Corporation
2
Agenda CodeDOM Introduction Assembly compilation Source code generation Source code parsing Advanced concepts Template based source code generation On-the-fly proxy generation
3
CodeDOM scenarios.NET Framework scenarios ASP.NET assembly generation WSDL proxy generation Managed C++ WinForms designer VS code wizards Custom scenarios Generation of typesafe collections Source code skeleton generation On the fly tie-pattern generation
4
CodeDOM namespaces System.CodeDom Contains the Code Document Object Model (CodeDOM) graph types System.CodeDom.Compiler Contract for all CodeDomProviders Contains interfaces and (abstract) base classes
5
CodeDOM providers Microsoft providers C#, VB.NET, Managed C++, Jscript, J# Microsoft partners NetCOBOL (Fujitsu) ActivePERL (ActiveState) Eiffel (Interactive Software Engineering) …
6
HelloWorld CodeDom graph namespace Samples { using System; public class Hello { public void SayHello() { Console.WriteLine("Hello World!"); } CompileUnit Namespaces Namespace Sample Imports System Types Class HelloWorld Members Method SayHello Statements Expression
7
CodeDOM graph Independent of programming language In-memory representation of a source code document Tree based object model Doesn’t support all language specific features (no unsafe, no variable declaration lists, …) Compiles if the root element is of type CodeCompileUnit
8
CodeDOM concepts public static void Main(String[] args ) { String usr; FileStream f; StreamWriter w; try { usr=Environment.GetEnvironmentVariable("USERNAME"); f=new FileStream(“C:\\test.txt",FileMode.Create); w=new StreamWriter(f); w.WriteLine(usr); w.Close(); } catch (Exception e){ Console.WriteLine("Exception:"+e.ToString()); } public static void Main(String[] args ) { String usr; FileStream f; StreamWriter w; try { usr=Environment.GetEnvironmentVariable("USERNAME"); f=new FileStream(“C:\\test.txt",FileMode.Create); w=new StreamWriter(f); w.WriteLine(usr); w.Close(); } catch (Exception e){ Console.WriteLine("Exception:"+e.ToString()); } Source code CodeDOM graph Assembly compiling compiling source code parsing source code generating
9
Programming model Creating the code provider CodeDomProvider provider = new Microsoft.CSharp.CSharpCodeProvider(); Obtaining the required interface ICodeGenerator generator = provider.CreateGenerator(); Calling the method generator.GenerateCodeFromCompileUnit(…);
10
CodeDOM Compiling an assembly on the fly In-memory stored to disk Generating code according to an in-memory CodeDOM graph Several code providers are already available (C#, VB.NET, J#, Managed C++) Parsing code to get an in-memory CodeDOM graph
11
Agenda CodeDOM Introduction Assembly compilation Source code generation Source code parsing Advanced concepts Template based source code generation On-the-fly proxy generation
12
Assembly compilation public static void Main(String[] args ) { String usr; FileStream f; StreamWriter w; try { usr=Environment.GetEnvironmentVariable("USERNAME"); f=new FileStream(“C:\\test.txt",FileMode.Create); w=new StreamWriter(f); w.WriteLine(usr); w.Close(); } catch (Exception e){ Console.WriteLine("Exception:"+e.ToString()); } public static void Main(String[] args ) { String usr; FileStream f; StreamWriter w; try { usr=Environment.GetEnvironmentVariable("USERNAME"); f=new FileStream(“C:\\test.txt",FileMode.Create); w=new StreamWriter(f); w.WriteLine(usr); w.Close(); } catch (Exception e){ Console.WriteLine("Exception:"+e.ToString()); } Source code CodeDOM graph Assembly compiling compiling source code parsing source code generating
13
Assembly compilation Motivations On-the-fly code generation and compilation Interface interception Compiled “scripting” support
14
ICodeCompiler (1/3) Compilation sources CodeCompileUnit (CodeDOM graph) Source file String containing source code Compilation methods Single compilation CompileAssemblyFromDom(…) CompileAssemblyFromFile(…) CompileAssemblyFromSource(…) Batch compilation CompileAssemblyFromDomBatch(…) CompileAssemblyFromFileBatch(…) CompileAssemblyFromSourceBatch(…)
15
ICodeCompiler (2/3) Compilation parameterization class CompilerParameters Compiler options GenerateExecutable (false => dll) GenerateInMemory OutputAssembly MainClass …
16
ICodeCompiler (3/3) Compilation results CompileAssemblyFrom… methods return CompileResults CompiledAssembly, Errors, Output, … Printing the compiler output to the screen: CompilerResults results = compiler.CompileAssemblyFromFile(options, src); foreach (string line in results.Output) { Console.WriteLine(line); }
17
Generating assemblies on the fly demo demo
18
Agenda CodeDOM Introduction Assembly compilation Source code generation Source code parsing Advanced concepts Template based source code generation On-the-fly proxy generation
19
Source code generation public static void Main(String[] args ) { String usr; FileStream f; StreamWriter w; try { usr=Environment.GetEnvironmentVariable("USERNAME"); f=new FileStream(“C:\\test.txt",FileMode.Create); w=new StreamWriter(f); w.WriteLine(usr); w.Close(); } catch (Exception e){ Console.WriteLine("Exception:"+e.ToString()); } public static void Main(String[] args ) { String usr; FileStream f; StreamWriter w; try { usr=Environment.GetEnvironmentVariable("USERNAME"); f=new FileStream(“C:\\test.txt",FileMode.Create); w=new StreamWriter(f); w.WriteLine(usr); w.Close(); } catch (Exception e){ Console.WriteLine("Exception:"+e.ToString()); } Source code CodeDOM graph Assembly compiling compiling source code parsing source code generating
20
Source code generation Motivations Avoiding repetitive coding tasks Generation of typed collections Pattern based code generation Tie pattern implementation Implementation of language independent code wizards and tools Designer support
21
HelloWorld CodeDom graph namespace Samples { using System; public class Hello { public void SayHello() { Console.WriteLine("Hello World!"); } CompileUnit Namespaces Namespace Sample Imports System Types Class HelloWorld Members Method SayHello Statements Expression
22
CodeDom elements (1/3) CodeObject Common base class for most CodeDOM objects CodeCompileUnit Container for a CodeDOM program graph CodeComment Represents a comment CodeExpression Base class for other code expression objects: CodeArrayCreateExpression CodeCastExpression CodeMethodInvokeExpression …
23
CodeDom elements (2/3) CodeNamespace Represents a namespace declaration CodeNamespaceImport Represents a namespace import directive CodeStatement Base class for other code statement objects: CodeAssignStatement CodeMethodReturnStatement CodeIterationStatement …
24
CodeDom elements (3/3) CodeTypeMember Base class for a member of a type: CodeMemberField CodeMemberMethod CodeConstructor CodeTypeConstructor (static ctor) CodeEntryPointMethod CodeMemberProperty … CodeTypeReference Represents a reference to a type
25
ICodeGenerator (1/3) Generation sources CodeCompileUnit CodeExpression CodeNamespace CodeStatement CodeTypeDeclaration Generation inputs CodeDOM element TextWriter Generation options
26
ICodeGenerator (2/3) Generation support verification Are arrays of arrays supported? Can I nest multiple types? Are goto statements supported? … CodeDomProvider provider = new Microsoft.CSharp.CSharpCodeProvider(); CodeDomProvider provider = new Microsoft.CSharp.CSharpCodeProvider(); ICodeGenerator generator = provider.CreateGenerator(); ICodeGenerator generator = provider.CreateGenerator(); if (generator.Supports(GeneratorSupport.NestedTypes) == false) if (generator.Supports(GeneratorSupport.NestedTypes) == false) { //we have a problem... //we have a problem... }
27
ICodeGenerator (3/3) Generation options Blank lines between members Bracing style (“Block” or “C”) Else on closing Indent string CodeGeneratorOptions options = new CodeGeneratorOptions(); options.BlankLinesBetweenMembers = true; options.BracingStyle = "C"; // options.BracingStyle = “Block"; options.ElseOnClosing = true; options.IndentString = " ";
28
Generating source code demo demo
29
Agenda CodeDOM Introduction Assembly compilation Source code generation Source code parsing Advanced concepts Template based source code generation On-the-fly proxy generation
30
Source code parsing public static void Main(String[] args ) { String usr; FileStream f; StreamWriter w; try { usr=Environment.GetEnvironmentVariable("USERNAME"); f=new FileStream(“C:\\test.txt",FileMode.Create); w=new StreamWriter(f); w.WriteLine(usr); w.Close(); } catch (Exception e){ Console.WriteLine("Exception:"+e.ToString()); } public static void Main(String[] args ) { String usr; FileStream f; StreamWriter w; try { usr=Environment.GetEnvironmentVariable("USERNAME"); f=new FileStream(“C:\\test.txt",FileMode.Create); w=new StreamWriter(f); w.WriteLine(usr); w.Close(); } catch (Exception e){ Console.WriteLine("Exception:"+e.ToString()); } Source code CodeDOM graph Assembly compiling compiling source code parsing source code generating
31
Source code parsing Motivations Enabling iterative designer/modeling support Source code migration Porting source code from one language into another
32
There is only one problem… CodeDomProvider csp = new Microsoft.CSharp.CSharpCodeProvider(); CodeDomProvider vbp = new Microsoft.VisualBasic.VBCodeProvider(); ICodeParser parser = csp.CreateParser(); ICodeGenerator generator = vbp.CreateGenerator(); CodeCompileUnit cu = parser.Parse(new StreamReader("Test.cs")); generator.GenerateCodeFromCompileUnit(cu, new StreamWriter("Test.vb"), new CodeGeneratorOptions());
33
…and no real solution to it Neither VB.NET, C# nor J# CodeDomProviders implement ICodeParser Managed C++ implements ICodeParser, but it works only in the VS.NET designer scenario Managed C++ implements a method based parser Returns a CodeStatementCollection Can’t be used for whole source files
34
Agenda CodeDOM Introduction Assembly compilation Source code generation Source code parsing Advanced concepts Template based source code generation On-the-fly proxy generation
35
public class List { private object[] elements; private object[] elements; private int count; private int count; public void Add(object element) { public void Add(object element) { if (count == elements.Length) Resize(count * 2); if (count == elements.Length) Resize(count * 2); elements[count++] = element; elements[count++] = element; } public object this[int index] { public object this[int index] { get { return elements[index]; } get { return elements[index]; } set { elements[index] = value; } set { elements[index] = value; } } public int Count { public int Count { get { return count; } get { return count; } }} Problem statement List intList = new List(); intList.Add(1); // Argument is boxed intList.Add(2); // Argument is boxed intList.Add("Three"); // Should be an error int i = (int)intList[0]; // Cast required
36
A possible solution public class IntList { private int[] elements; private int[] elements; private int count; private int count; public void Add(int element) { public void Add(int element) { if (count == elements.Length) Resize(count * 2); if (count == elements.Length) Resize(count * 2); elements[count++] = element; elements[count++] = element; } public int this[int index] { public int this[int index] { get { return elements[index]; } get { return elements[index]; } set { elements[index] = value; } set { elements[index] = value; } } public int Count { public int Count { get { return count; } get { return count; } }} IntList intList = new IntList(); intList.Add(1); // No boxing intList.Add(2); // No boxing intList.Add("Three"); // Compile-time error int i = intList[0]; // No cast required
37
Template based source code generation Motivations Avoiding the generic approach Downcasting/boxing is expensive Type safety can’t be guaranteed Base class can’t be chosen for a given implementation class A : Immutable class A : Volatile All this (and more) will be addressed through.NET Generics as well!
38
Generating parameterized types Collectiongraph public static void Main(String[] args ) { String usr; FileStream f; StreamWriter w; try { usr=Environment.GetEnvironmentVariable("USERNAME"); f=new FileStream(“C:\\test.txt",FileMode.Create); w=new StreamWriter(f); w.WriteLine(usr); w.Close(); } catch (Exception e){ Console.WriteLine("Exception:"+e.ToString()); } public static void Main(String[] args ) { String usr; FileStream f; StreamWriter w; try { usr=Environment.GetEnvironmentVariable("USERNAME"); f=new FileStream(“C:\\test.txt",FileMode.Create); w=new StreamWriter(f); w.WriteLine(usr); w.Close(); } catch (Exception e){ Console.WriteLine("Exception:"+e.ToString()); } StringCollection public static void Main(String[] args ) { String usr; FileStream f; StreamWriter w; try { usr=Environment.GetEnvironmentVariable("USERNAME"); f=new FileStream(“C:\\test.txt",FileMode.Create); w=new StreamWriter(f); w.WriteLine(usr); w.Close(); } catch (Exception e){ Console.WriteLine("Exception:"+e.ToString()); } public static void Main(String[] args ) { String usr; FileStream f; StreamWriter w; try { usr=Environment.GetEnvironmentVariable("USERNAME"); f=new FileStream(“C:\\test.txt",FileMode.Create); w=new StreamWriter(f); w.WriteLine(usr); w.Close(); } catch (Exception e){ Console.WriteLine("Exception:"+e.ToString()); } Int32Collection public static void Main(String[] args ) { String usr; FileStream f; StreamWriter w; try { usr=Environment.GetEnvironmentVariable("USERNAME"); f=new FileStream(“C:\\test.txt",FileMode.Create); w=new StreamWriter(f); w.WriteLine(usr); w.Close(); } catch (Exception e){ Console.WriteLine("Exception:"+e.ToString()); } public static void Main(String[] args ) { String usr; FileStream f; StreamWriter w; try { usr=Environment.GetEnvironmentVariable("USERNAME"); f=new FileStream(“C:\\test.txt",FileMode.Create); w=new StreamWriter(f); w.WriteLine(usr); w.Close(); } catch (Exception e){ Console.WriteLine("Exception:"+e.ToString()); } FooCollectionSystem.String System.Int32 Nonsense.Foo
39
Implementation tips Parameterize the creation of the CodeDOM graph Types Type names Namespace names CodeTypeDeclaration cs = new CodeTypeDeclaration(typeName); CodeMemberField count = new CodeMemberField(type, "count"); CodeNamespace ns = new CodeNamespace(namespaceName);
40
Template based source code generation demo demo
41
Agenda CodeDOM Introduction Assembly compilation Source code generation Source code parsing Advanced concepts Template based source code generation On-the-fly proxy generation
42
Motivations Method call interception Ensure thread safety Logging/tracing Tie-generation Making an interface aware of the implementation context
43
Generating proxiesType (Assembly) ProxyAssembly public static void Main(String[] args ) { String usr; FileStream f; StreamWriter w; try { usr=Environment.GetEnvironmentVariable("USERNAME"); f=new FileStream(“C:\\test.txt",FileMode.Create); w=new StreamWriter(f); w.WriteLine(usr); w.Close(); } catch (Exception e){ Console.WriteLine("Exception:"+e.ToString()); } public static void Main(String[] args ) { String usr; FileStream f; StreamWriter w; try { usr=Environment.GetEnvironmentVariable("USERNAME"); f=new FileStream(“C:\\test.txt",FileMode.Create); w=new StreamWriter(f); w.WriteLine(usr); w.Close(); } catch (Exception e){ Console.WriteLine("Exception:"+e.ToString()); } Source Proxy graph Reflection Injection Generation Compilation Reflected graph
44
Implementation tips (1/5) Only type contracts are reflectable No managed access to implementation Intercept interfaces not classes Simplifies programming model Generate constructors that initialize the underlying instance Be aware of unsupported constructs Unsafe (string’s char*) Nested namespaces Use IsSpecialName to detect property and event methods
45
Implementation tips (2/5) Interface interception public Interface IFoo { int foo(int i); } public class A : B, IFoo { public A(string name){;} public int foo(int i){;} public int doIt(){;} } public class Proxy : C, IFoo { private A __tieObject; public Proxy(string name) { // pre ctor injection __tieObj = new A(name); // post ctor injection } public int foo(int i) { // pre method call injection int __returnValue; __returnValue = __tieObj.foo(i); // post method call injection return __returnValue; }
46
Implementation tips (3/5) Delegates and events allow flexible code injection public delegate void MethodCallInjection(CodeMemberMethod mm, MethodInfo mi); public delegate void CtorCallInjection(CodeConstructor cc, ConstructorInfo ci); public delegate void PropertyCallInjection(CodeMemberProperty mp, PropertyInfo pi); public event MethodCallInjection OnPreMethodCallInjection; public event MethodCallInjection OnMethodCallInjection; public event MethodCallInjection OnPostMethodCallInjection; public event CtorCallInjection OnPreCtorCallInjection; …
47
Implementation tips (4/5) Injection delegate implementation public void ParamCheckInjection(CodeMemberMethod mm, MethodInfo mi) { foreach (ParameterInfo pi in mi.GetParameters()) { mm.Statements.Add( new CodeExpressionStatement( new CodeMethodInvokeExpression( new CodeMethodReferenceExpression( new CodeTypeReferenceExpression("System.Console"), "WriteLine”), new CodePrimitiveExpression(pi.Name + ": {0}"), new CodeMethodInvokeExpression(new CodeVariableReferenceExpression(pi.Name), "ToString")))); } XmlNodeList SelectNodes(string xpath, XmlNamespaceManager nsmgr) { System.Console.WriteLine("xpath: {0}", xpath.ToString()); System.Console.WriteLine("nsmgr: {0}", nsmgr.ToString());
48
Implementation tips (5/5) Creating an injected instance public object CreateInstance(string typeName, params object[] args) { Type[] types = new Type[args.Length]; for (int i=0; i < args.Length; i++) { types[i] = args[i].GetType(); } Type injectedType = compiledAssembly.GetType(typeName, true); ConstructorInfo ci = injectedType.GetConstructor(types); return ci.Invoke(args); } IFoo iProxy = (IFoo) xxx.CreateInstance(“Proxy”, “Hello”); int s = iProxy.Foo(2);
49
On-the-fly proxy generation demo demo
50
Agenda CodeDOM Introduction Assembly compilation Source code generation Source code parsing Advanced concepts Template based source code generation On-the-fly proxy generation Summary
51
Assembly compilation On-the-fly code generation and compilation Source code generation Avoiding repetitive coding tasks Pattern based code generation Implementation of language independent code wizards and tools Source code parsing Enabling iterative designer/modeling support Source code migration
52
Ask The Experts Get Your Questions Answered I will be available in the ATE area after this session
53
Community Resources http://www.microsoft.com/communities/default.mspx Most Valuable Professional (MVP) http://www.mvp.support.microsoft.com/ Newsgroups Converse online with Microsoft Newsgroups, including Worldwide http://www.microsoft.com/communities/newsgroups/default.mspx User Groups Meet and learn with your peers http://www.microsoft.com/communities/usergroups/default.mspx
54
evaluations evaluations
55
© 2003 Microsoft Corporation. All rights reserved. This presentation is for informational purposes only. MICROSOFT MAKES NO WARRANTIES, EXPRESS OR IMPLIED, IN THIS SUMMARY.
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.