Source Viewer: MorphArray.cs
Font Size:
1
2
3
4
5
6
7
MorphArray.cs
Morpho.cs
MyWebClient.cs
PronounceWord.cs
syslog.cs
SyslogTraceListener.cs
MQ
..
// // MorphArray.cs // // Morphs an array of objects of types with public fields into an array // of objects of types with public properties. // // This class accepts an array of objects of a given 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). // Finally, an array of objects of the new type is instantiated, // one for each object in the original array. // // // 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. It serves as 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; // } // } // } // } // // // example usage: // // get an array from a GLUE webservice: // glue.webservice.OrderInfo[] oia= wsproxy.getOrdersForCustomer(TextBox1.Text); // // generate a morphed array suitable for use in a DataGrid: // DataGrid1.DataSource= MorphArray(oia); // // // If using winForms - then the referencedAssemblies for the // System.CodeDom.Compiler.CompilerParameters will need to be // modified to include whatever DLLs are appropriate. // // // Wed, 11 Dec 2002 00:58 // // (c) 2003, ionic shade // private object[] MorphArray(object[] a) { System.Type mt= a[0].GetType(); 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")); 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 type System.CodeDom.CodeMemberField field1; field1= new System.CodeDom.CodeMemberField(); field1.Attributes = System.CodeDom.MemberAttributes.Private; field1.Name= "m_wrapped"; field1.Type=new System.CodeDom.CodeTypeReference(mt); class1.Members.Add(field1); // morph each public field of the wrapped type 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; // fail 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); // 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 codeDom graph // for asp.net usage - reference the DLLs in the bin dir for the compile: System.Collections.ArrayList referencedAssemblies = new System.Collections.ArrayList(); System.IO.DirectoryInfo di = new System.IO.DirectoryInfo( "bin" ); System.IO.FileInfo[] fiArr = di.GetFiles(); for (int j=0; j < fiArr.Length; j++) { if (fiArr[j].Extension.Equals(".dll")) referencedAssemblies.Add("bin\\" + fiArr[j].Name); } System.CodeDom.Compiler.CompilerParameters compilerParameters = new System.CodeDom.Compiler.CompilerParameters((string[])referencedAssemblies.ToArray(typeof(string))); 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 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; // fail // successful compile - now use the generated assembly System.Reflection.Assembly assy= compilerResults.CompiledAssembly; System.Collections.ArrayList args; System.Collections.ArrayList result= new System.Collections.ArrayList(); for (int i=0; i < a.Length; i++) { args= new System.Collections.ArrayList(); // invoke the 'copy' constructor args.Add(a[i]); // pass in the original object 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); result.Add(o); // add the resulting new object to the list } // return the list of new objects return (object[])result.ToArray(typeof(object)); }
The srcview page has been enjoyed 291574 times since 18 September 2003