Source Viewer:  Morpho.cs

Font Size:
MorphArray.cs  Morpho.cs  MyWebClient.cs  PronounceWord.cs  syslog.cs  SyslogTraceListener.cs 
MQ  .. 

// morpho.cs // // This class accepts a type, and using System.CodeDom, generates a new type, // which wraps the original type. Each of the public fields in the original // type is exposed as a public property in the generated type. The dynamically- // generated type is then compiled (in memory) and is ready for use by the // application. // // Why is this useful? // // 1. DataGrids and other data-bound controls can use arrays of // objects as data sources, but they display only public properties (not fields). // A typical scenario is a type that is returned from a web services call from // a Java platform. The wsdl.exe compiler produces a type with public FIELDS, // not properties. This sample shows how to morph those types into something // a data-bound control can use. // // 2. A short illustration of how to use System.CodeDom // // // Example: // for an input type like so: // // public class MyClassWithFields { // public int IntField; // public string StringField; // public long LongField; // public byte ByteField; // } // // // this is what the generated wrapper type looks like: // // namespace GeneratedWrapper { // // // Wrapper class for MyClassWithFields // public class MyClassWithFields { // private dinoch.demo.MyClassWithFields m_wrapped; // // the null constructor // public MyClassWithFields() { // m_wrapped = new dinoch.demo.MyClassWithFields(); // } // // the 'copy' constructor // public MyClassWithFields(dinoch.demo.MyClassWithFields X) { // m_wrapped = X; // } // public virtual int IntField { // get { // return m_wrapped.IntField; // } // set { // m_wrapped.IntField = value; // } // } // public virtual string StringField { // get { // return m_wrapped.StringField; // } // set { // m_wrapped.StringField = value; // } // } // public virtual long LongField { // get { // return m_wrapped.LongField; // } // set { // m_wrapped.LongField = value; // } // } // public virtual System.Byte ByteField { // get { // return m_wrapped.ByteField; // } // set { // m_wrapped.ByteField = value; // } // } // } // } // namespace dinoch.demo { public class Morpho { public static object MorphObject(object a) { System.Type mt= a.GetType(); // generate the assembly // use same name (but it will be in a different namespace) System.CodeDom.CodeTypeDeclaration class1 = new System.CodeDom.CodeTypeDeclaration(mt.Name); class1.IsClass=true; class1.TypeAttributes = System.Reflection.TypeAttributes.Public; class1.Comments.Add(new System.CodeDom.CodeCommentStatement("Wrapper class for " + mt.Name)); System.CodeDom.CodeConstructor ctor; ctor= new System.CodeDom.CodeConstructor(); ctor.Attributes = System.CodeDom.MemberAttributes.Public; ctor.Comments.Add(new System.CodeDom.CodeCommentStatement("the null constructor")); class1.Members.Add(ctor); ctor.Statements.Add(new System.CodeDom.CodeAssignStatement(new System.CodeDom.CodeVariableReferenceExpression("m_wrapped"), new System.CodeDom.CodeObjectCreateExpression(mt))); ctor= new System.CodeDom.CodeConstructor(); ctor.Attributes = System.CodeDom.MemberAttributes.Public; ctor.Comments.Add(new System.CodeDom.CodeCommentStatement("the 'copy' constructor")); class1.Members.Add(ctor); ctor.Parameters.Add(new System.CodeDom.CodeParameterDeclarationExpression(mt,"X")); // arg name is arbitrary ctor.Statements.Add(new System.CodeDom.CodeAssignStatement(new System.CodeDom.CodeVariableReferenceExpression("m_wrapped"), new System.CodeDom.CodeVariableReferenceExpression("X"))); // embed a local (private) copy of the wrapped object System.CodeDom.CodeMemberField field1; field1= new System.CodeDom.CodeMemberField(); field1.Attributes = System.CodeDom.MemberAttributes.Private; field1.Name= "m_wrapped"; // this is the name of the wrapped object field1.Type=new System.CodeDom.CodeTypeReference(mt); class1.Members.Add(field1); // morph each public field into a property in the wrapper object System.CodeDom.CodeMemberProperty prop1; System.CodeDom.CodeAssignStatement setter ; System.Reflection.FieldInfo[] fia= mt.GetFields(); if ((fia == null) || (fia.Length == 0)) return null; foreach (System.Reflection.FieldInfo fi in fia) { prop1= new System.CodeDom.CodeMemberProperty(); prop1.Attributes = System.CodeDom.MemberAttributes.Public; prop1.Name= fi.Name; prop1.Type=new System.CodeDom.CodeTypeReference(fi.FieldType); // TODO: test if field is readonly before adding setter // set {m_fieldValue= value;} setter= new System.CodeDom.CodeAssignStatement(new System.CodeDom.CodeVariableReferenceExpression(field1.Name + "." + fi.Name), new System.CodeDom.CodeVariableReferenceExpression("value")); prop1.SetStatements.Add(setter); // get {return m_fieldValue;} prop1.GetStatements.Add(new System.CodeDom.CodeMethodReturnStatement(new System.CodeDom.CodeSnippetExpression(field1.Name + "." + fi.Name))); class1.Members.Add(prop1); } // compile the generated assembly System.Collections.ArrayList referencedAssemblies= null; try { System.IO.DirectoryInfo di = new System.IO.DirectoryInfo( "bin" ); System.IO.FileInfo[] fiArr = di.GetFiles(); referencedAssemblies = new System.Collections.ArrayList(); for (int j=0; j < fiArr.Length; j++) { if (fiArr[j].Extension.Equals(".dll")) referencedAssemblies.Add("bin\\" + fiArr[j].Name); } } catch (System.IO.DirectoryNotFoundException dnfe) { } System.CodeDom.Compiler.CompilerParameters compilerParameters= null; if (referencedAssemblies != null) compilerParameters= new System.CodeDom.Compiler.CompilerParameters((string[])referencedAssemblies.ToArray(typeof(string))); else compilerParameters= new System.CodeDom.Compiler.CompilerParameters(); compilerParameters.GenerateInMemory=true; System.CodeDom.CodeNamespace nameSpace = new System.CodeDom.CodeNamespace("GeneratedWrapper"); nameSpace.Types.Add(class1); System.CodeDom.CodeCompileUnit compileUnit = new System.CodeDom.CodeCompileUnit(); compileUnit.Namespaces.Add(nameSpace); Microsoft.CSharp.CSharpCodeProvider csharp = new Microsoft.CSharp.CSharpCodeProvider(); #if DISPLAY_GENERATED_CODE // display the generated code. // (could also generate in VB here. ) System.CodeDom.Compiler.ICodeGenerator csharpGtor = csharp.CreateGenerator(); System.IO.StringWriter sw= new System.IO.StringWriter(); System.CodeDom.Compiler.IndentedTextWriter tw= new System.CodeDom.Compiler.IndentedTextWriter(sw); System.CodeDom.Compiler.CodeGeneratorOptions z= new System.CodeDom.Compiler.CodeGeneratorOptions(); z.BlankLinesBetweenMembers = false; z.IndentString=" "; csharpGtor.GenerateCodeFromCompileUnit(compileUnit, tw, z); System.Console.WriteLine(sw.ToString()); #endif // actually compile the generated code into an in-memory assembly: //Microsoft.CSharp.CSharpCodeProvider csharp = new Microsoft.CSharp.CSharpCodeProvider(); //could also use System.CodeDom.Compiler.ICodeCompiler csharpCompiler = csharp.CreateCompiler(); System.CodeDom.Compiler.CompilerResults compilerResults = csharpCompiler.CompileAssemblyFromDom(compilerParameters,compileUnit); if ( compilerResults != null && compilerResults.Errors.Count > 0 ) return null; // successful compile - now use the generated assembly. // instantiate the type with the "copy constructor" System.Reflection.Assembly assy= compilerResults.CompiledAssembly; System.Collections.ArrayList args= new System.Collections.ArrayList(); args.Add(a); object o = assy.CreateInstance("GeneratedWrapper." + mt.Name, false, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.InvokeMethod, null, (object[])args.ToArray(typeof(object)), null, null); return o ; } // public static object MorphObject(object a) } } // for an input object like so: // // public class MyClassWithFields { // public int IntField; // public string StringField; // public long LongField; // public byte ByteField; // } // // // this is what the generated wrapper class looks like: // // namespace GeneratedWrapper { // // // Wrapper class for MyClassWithFields // public class MyClassWithFields { // private dinoch.demo.MyClassWithFields m_wrapped; // // the null constructor // public MyClassWithFields() { // m_wrapped = new dinoch.demo.MyClassWithFields(); // } // // the 'copy' constructor // public MyClassWithFields(dinoch.demo.MyClassWithFields X) { // m_wrapped = X; // } // public virtual int IntField { // get { // return m_wrapped.IntField; // } // set { // m_wrapped.IntField = value; // } // } // public virtual string StringField { // get { // return m_wrapped.StringField; // } // set { // m_wrapped.StringField = value; // } // } // public virtual long LongField { // get { // return m_wrapped.LongField; // } // set { // m_wrapped.LongField = value; // } // } // public virtual System.Byte ByteField { // get { // return m_wrapped.ByteField; // } // set { // m_wrapped.ByteField = value; // } // } // } // } //

The srcview page has been enjoyed 291584 times since 18 September 2003