Det er ret normalt på compile time at generere klasser udfra tabeller eller tabeller udfra klasser.
Det kan de såkaldte O/R mappere gøre.
Det er lidt usædvaneligt at ville gøre det runtime.
Hvorfor kan du ikke bare slå op med navn i en eller anden collection ? Du kan jo alligevel ikke bruge de dynamisk genererede properties i din kode, da de ikke er kendte på compile time.
Hvis du virkeligt vil gøre det, så skal vi over i noget dynamisk kode generering.
Jeg kan godt lave et eksempel, men overvej lige om det faktisk er noget du har brug for.
using System; using System.Collections.Generic; using System.Data; using System.Data.SqlClient; using System.Text; using System.Reflection; using System.CodeDom.Compiler;
using Microsoft.CSharp;
namespace E { public class Data { public virtual string Name { get { return "<incomplete>"; } } } public static class OR { private const string nstemp = @"using System; using E; namespace ORGen {{ {0} }}"; private const string clztemp = @"public class {0} : {1} {{ {2} }}"; private const string fldtemp = @"private {0} {1};"; private const string proptemp = @"public {0} {1} {{ get {{ return {2}; }} set {{ {2} = value; }} }}"; private const string namtemp = @"public string Name {{ get {{ return ""{0}""; }} }}"; public static Type Extend(Type baseclz, IDbConnection con, string tblnam) { StringBuilder sb = new StringBuilder(); IDbCommand cmd = con.CreateCommand(); cmd.CommandText = "SELECT COLUMN_NAME,DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='" + tblnam + "'"; IDataReader rdr = cmd.ExecuteReader(); while(rdr.Read()) { string colnam = (string)rdr[0]; colnam = colnam.ToLower(); string propnam = colnam.ToUpper()[0] + colnam.Substring(1); string coltyp = (string)rdr[1]; if(coltyp == "int") { // OK } else if(coltyp == "varchar") { coltyp = "string"; } else { throw new Exception(coltyp + " not supported"); } sb.Append(String.Format(fldtemp, coltyp, colnam)); sb.Append(String.Format(proptemp, coltyp, propnam, colnam, colnam)); } rdr.Close(); sb.Append(String.Format(namtemp, tblnam)); string src = String.Format(nstemp, String.Format(clztemp, tblnam, baseclz.FullName, sb.ToString())); CodeDomProvider comp = new CSharpCodeProvider(); CompilerParameters param = new CompilerParameters(); param.GenerateInMemory = true; param.ReferencedAssemblies.Add("System.dll"); param.ReferencedAssemblies.Add(Assembly.GetExecutingAssembly().Location); CompilerResults res = comp.CompileAssemblyFromSource(param, src); Assembly asm = res.CompiledAssembly; return asm.GetType("ORGen." + tblnam); } } public static class ORUtil { private static IDbConnection con; private static Dictionary<string,Type> cache = new Dictionary<string,Type>(); public static IDbConnection Con { set { con = value; } } public static Type Extend(string tblnam) { if(!cache.ContainsKey(tblnam)) { cache.Add(tblnam, OR.Extend(typeof(Data), con, tblnam)); } return cache[tblnam]; } public static Data Read(IDataReader rdr, string tblnam) { Data res = (Data)Extend(tblnam).GetConstructor(new Type[0]).Invoke(new object[0]); for(int i = 0; i < rdr.FieldCount; i++) { if(!rdr.IsDBNull(i)) { res.GetType().GetProperty(rdr.GetName(i)).SetValue(res, rdr.GetValue(i), null); } } return res; } public static IList<Data> ReadAll(IDataReader rdr, string tblnam) { IList<Data> res = new List<Data>(); while(rdr.Read()) { res.Add(Read(rdr, tblnam)); } rdr.Close(); return res; } public static IList<Data> ReadAll(string tblnam) { IDbCommand cmd = con.CreateCommand(); cmd.CommandText = "SELECT * FROM " + tblnam; IDataReader rdr = cmd.ExecuteReader(); return ReadAll(rdr, tblnam); } } public class Program { public static void Main(string[] args) { Data o = new Data(); foreach(PropertyInfo pi in o.GetType().GetProperties()) { Console.WriteLine(pi.Name + " = " + pi.GetValue(o, null)); } SqlConnection con = new SqlConnection("server=ARNEPC3\\SQLEXPRESS;Integrated Security=SSPI;database=Test"); con.Open(); ORUtil.Con = con; Type x = ORUtil.Extend("T1"); Data ox = (Data)x.GetConstructor(new Type[0]).Invoke(new object[0]); foreach(PropertyInfo pi in ox.GetType().GetProperties()) { Console.WriteLine(pi.Name + " = " + pi.GetValue(ox, null)); } IList<Data> lst = ORUtil.ReadAll("T1"); foreach(Data d in lst) { foreach(PropertyInfo pi in d.GetType().GetProperties()) { Console.WriteLine(pi.Name + " = " + pi.GetValue(d, null)); } } con.Close(); Console.ReadKey(); } } }
Sært - jeg troede faktisk at jeg havde postet den.
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.