Avatar billede skov_p Praktikant
27. januar 2008 - 00:44 Der er 7 kommentarer og
1 løsning

Opret properties runtime

Her er en af de svære (synes jeg)

Jeg har en ordretable med følgende kolonner:
Recid (int)
OrderId (string)
CustomerId (int)
Created (DateTime)

Jeg har en ordre klasse der laver noget SQL

Nu vil jer gerne have oprettet en property for hver kolonne der er i tabellen og dens navn skal være kolonne navnet.

Dvs. at hvis jeg tilføjer en kolonne kommer der endnu en property i min klasse.

Jeg havde tænkt mig at lave en

public void SetProperty(string name, object val){...}

som sætter værdien på den property der har navnet i name parameteren.

Et lille kode-eksempel ville være lækkert.
Avatar billede arne_v Ekspert
27. januar 2008 - 02:23 #1
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.
Avatar billede skov_p Praktikant
27. januar 2008 - 10:41 #2
Jeg var ved at kigge på noget hvor jeg havde dem liggende i et dictonary, men jeg mangler at kunne noget i retningen af

public Prop GetProperty(Type t, string name){...};

Der returnerer et prop element af typen t feks. DateTime

Det skal være muligt at tilføje en kolonne og få indholdet vist i feks. en tekst boks ved hjælp af en bruger opsætning
Avatar billede arne_v Ekspert
28. januar 2008 - 04:57 #3
Følgende kode er absolut ikke production grade, men det viser at det kan lade sig gøre:

using System;
using System.Data;
using System.Data.SqlClient;
using System.Reflection;
using System.CodeDom.Compiler;

using Microsoft.CSharp;

namespace E
{
    public class T1
    {
        public virtual string Name
        {
            get
            {
                return "incomplete";
            }
        }
    }
    public static class OR
    {
        public static Type Extend(Type baseclz, IDbConnection con, string tblnam)
        {
            string[] baseparts = baseclz.FullName.Split(".".ToCharArray());
            string newclznam = baseclz.FullName + "Ext";
            string[] newparts = newclznam.Split(".".ToCharArray());
            string src = "using System;";
            src = src + "namespace " + newparts[0] + " {";
            src = src + "public class " + newparts[1] + " : " + baseparts[1] + " { ";
            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];
                string coltyp = (string)rdr[1];
                if(coltyp == "int")
                {
                    // OK
                }
                else if(coltyp == "varchar")
                {
                    coltyp = "string";
                }
                else
                {
                    throw new Exception(coltyp + " not supported");
                }
                src = src + "private " + coltyp + " " + colnam.ToLower() + "; ";
                colnam = colnam.ToUpper()[0] + colnam.ToLower().Substring(1);
                src = src + "public " + coltyp + " " + colnam + " { get { return " + colnam.ToLower() + "; } set { " + colnam.ToLower() + " = value; } }";
            }
            src = src + "public override string Name { get { return \"The real " + baseparts[1] + "\"; } }";
            src = src + "} }";
            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(newclznam);
        }
    }
    public class Program
    {
        public static void Main(string[] args)
        {
            T1 o = new T1();
            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();
            Type x = OR.Extend(typeof(T1), con, "T1");
            T1 ox = (T1)x.GetConstructor(new Type[0]).Invoke(new object[0]);
            foreach(PropertyInfo pi in ox.GetType().GetProperties())
            {
                Console.WriteLine(pi.Name + " = " + pi.GetValue(ox, null));
            }
            con.Close();
            Console.ReadKey();
        }
    }
}
Avatar billede skov_p Praktikant
19. februar 2008 - 21:46 #4
Tak for hjælpen, smid et svar
Avatar billede arne_v Ekspert
19. februar 2008 - 22:10 #5
kommer her
Avatar billede arne_v Ekspert
19. februar 2008 - 22:11 #6
Hvis du vilr fortsaette med ideen, saa fik jeg vist lavet en forbedret udgave af ovenstaaende kode.
Avatar billede arne_v Ekspert
20. februar 2008 - 00:38 #7
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();
        }
    }
}
Avatar billede arne_v Ekspert
20. februar 2008 - 00:38 #8
Sært - jeg troede faktisk at jeg havde postet den.
Avatar billede Ny bruger Nybegynder

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.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester