Avatar billede decrypto Nybegynder
13. marts 2007 - 13:23 Der er 26 kommentarer og
1 løsning

Oprettelse af dynamiske klasser

Jeg har et meget interessant spørgsmål. Jeg vil gerne prøve at bygge dynamiske klasser op. Disse klasse skal bygges op efter data jeg henter fra en DB.

Jeg har nemlig en produkt database og hver produkt indeholder nogle services.

Ideeen er at jeg gerne vil lave en klasse pr. produktnavn, og metoder pr. service. Input parametre skal der ikke bekymres om i første omgang.

Hvordan er det smartest at lave sådan een. Jeg har ledt på nettet, men eksemplerne er en smule lange og for langhåret.

Nogen der kan hjælpe? eller måske frarråde det?....

Det vil ellers gør ting dynamisk, hvis det kunne lade sig gøre.
Avatar billede arne_v Ekspert
13. marts 2007 - 13:38 #1
Du kan godt create klasser dynamisk at runtime. .NET frameworket har indbygget
compiler.

Men den slags er ikke helt simpelt.

Jeg har også nogle eksempler.
Avatar billede arne_v Ekspert
13. marts 2007 - 13:39 #2
using System;
using System.Reflection;
using System.CodeDom.Compiler;

using Microsoft.CSharp;

namespace E
{
    class MainClass
    {
        public static void Main(string[] args)
        {
            string src = @"public class X
{
    public override string ToString()
    {
        return ""I am a X"";
    }
};";
            ICodeCompiler comp = (new CSharpCodeProvider()).CreateCompiler();
            CompilerParameters param = new CompilerParameters();
            param.GenerateInMemory = true;
            param.ReferencedAssemblies.Add("System.dll");
            CompilerResults res = comp.CompileAssemblyFromSource(param, src);
            Assembly asm = res.CompiledAssembly;
            object o = asm.CreateInstance("X");
            Console.WriteLine(o);
        }
    }
}

er relativt simpelt !
Avatar billede decrypto Nybegynder
13. marts 2007 - 14:10 #3
Ligger klassen 'in memory' eller kommer der en fysisk fil på disk?
Avatar billede decrypto Nybegynder
13. marts 2007 - 14:13 #4
Jeg får en obsolete besked på denne ->
(new CSharpCodeProvider()).CreateCompiler();

har du nogen ide om, hvad jeg kan / skal bruge?
Avatar billede arne_v Ekspert
13. marts 2007 - 15:15 #5
gaet paa hvad

param.GenerateInMemory = true;

goer ...

:-)
Avatar billede arne_v Ekspert
13. marts 2007 - 15:15 #6
De aendrede et eller andet i .NET 1.1 til 2.0.

Jeg kan proeve at find eud af hvad den anbefaldede metode er idag.
Avatar billede decrypto Nybegynder
13. marts 2007 - 15:51 #7
:-)

Hvordan kan jeg teste det?
Avatar billede arne_v Ekspert
13. marts 2007 - 16:12 #8
mit lille eksempel er koere klart som console app

og selv om det er deprecated, saa boer det stadig virke

og jeg skal nok finde den ikke deprecated metode at faa fat i compileren paa

senere
Avatar billede crazysnap Seniormester
13. marts 2007 - 17:45 #9
Hej decrypto,

Du kan sådan set også bare gøre sådan her for at initialisere en klasse dynamisk:



namespace TestNamespace
{
    class Test
    {
        public override string ToString()
        {
            return "Test class";
        }
    }

    static class Program
    {
        [STAThread]
        static void Main()
        {
            string strClassName = "Test";

            Assembly assembly = Assembly.GetExecutingAssembly();

            Type tObj = assembly.GetType("TestNamespace." + strClassName);

            //Exempel 1: Intialiser en ny instans af Test klassen (caster den til test klassen)
            Test objTest = (Test)tObj.GetConstructor(new Type[] { }).Invoke(new object[] { });

            //Exempel 2: Intialiser en ny instans af Test klassen uden at caste den
            Object objTest2 = tObj.GetConstructor(new Type[] { }).Invoke(new object[] { });

                        //Kalder den overridede ToString på Test obejkterne
            Console.WriteLine(objTest.ToString());
            Console.WriteLine(objTest2.ToString());

        }
    }
}


Dette virker ihvertfald fint i .NET 2.0 og er ikke deprecated (obsolete).  :)


Mvh.

- Snap :)
Avatar billede crazysnap Seniormester
13. marts 2007 - 17:46 #10
Og du skal lige huske:


using System.Reflection;


For at kunne få fat i "Assembly" :)


Mvh.

- Snap
Avatar billede arne_v Ekspert
13. marts 2007 - 18:17 #11
At opbygge klasser dynamisk og at loade klasser dynamisk er to meget forskellige ting.
Avatar billede crazysnap Seniormester
13. marts 2007 - 18:19 #12
Nå for søren, kan være jeg skal læse spørgsmålet ordentligt så. :)

Godt så, hvis der er tale om opbygning så spring straks mit eksempel over.


Mvh.

- Snap :)
Avatar billede arne_v Ekspert
13. marts 2007 - 18:22 #13
Det er jo ogsaa muligt at det er mig som er igang med et mega overkill.
Avatar billede arne_v Ekspert
13. marts 2007 - 18:23 #14
http://msdn2.microsoft.com/en-us/library/microsoft.csharp.csharpcodeprovider.aspx

antyder at:

ICodeCompiler comp = (new CSharpCodeProvider()).CreateCompiler();

skal vaere:

CodeDomProvider comp = CodeDomProvider.CreateProvider("CSharp");
Avatar billede hmortensen Nybegynder
13. marts 2007 - 23:20 #15
Og her er arnes kodestykke i udbygget version, som viser hvordan du kan kalde metoder (her vist med et parameter).

using System;
using System.Reflection;
using System.CodeDom.Compiler;
using Microsoft.CSharp;

namespace E
{
  class MainClass
  {
    public static void Main(string[] args)
    {
      string src = @"
        public class X
        {
          public int Number(int parm)
          {
            return ++parm;
          }
        };
      ";
      CodeDomProvider comp = CodeDomProvider.CreateProvider("CSharp");
      CompilerParameters param = new CompilerParameters();
      param.GenerateInMemory = true;
      param.ReferencedAssemblies.Add("System.dll");
      CompilerResults res = comp.CompileAssemblyFromSource(param, src);
      Assembly asm = res.CompiledAssembly;
      Type dynamicType = asm.GetType("X");
      object o = Activator.CreateInstance(dynamicType);
      MethodInfo mi = dynamicType.GetMethod("Number");
      Console.WriteLine(mi.Invoke(o, new Object[] { 5 }));
    }
  }
}
Avatar billede decrypto Nybegynder
14. marts 2007 - 09:23 #16
Dejligt....jeg prøver mig lige frem....

Synes begge to fortjener point...smid svar ind, så deler jeg kagen.
Avatar billede decrypto Nybegynder
14. marts 2007 - 09:29 #17
Udover det Arne...så har jeg lige den der Oracle listener issue...måske kan du også hjælpe der?

http://www.eksperten.dk/spm/767329
Avatar billede decrypto Nybegynder
14. marts 2007 - 10:55 #18
Inden svarene kommer ind....har jeg lige en lille detalje...

De her dynamiske klasser, skal de mere forstås some et interface eller et abstraktionslag? For hvordan laver jeg implementationen af mine metoder.

Ideelt vil jeg jo 'bare' kalde lave en instans af en anden klasse og så kalde metoden dernede hvor implementationen også vil være.
Avatar billede decrypto Nybegynder
14. marts 2007 - 11:15 #19
Og endnu vigtiger.....hvordan kan jeg instansiere en en class X

og på objektet fx gøre brug af en GetMessage() metode, der bare returnere en "Hello World"?
Avatar billede decrypto Nybegynder
14. marts 2007 - 11:58 #20
Ideen er at kunne lave en instans af klassen X, og så dotte sig til de metoder den tilbyder.
Avatar billede crazysnap Seniormester
14. marts 2007 - 12:09 #21
Hej decrypto,

Så var det jo bare så simpelt. Du skal bare cast'e dem til den klasse som du ved objektet er. Hvis vi tager udgangspunkt i hmortensens eksempel så bare gør følgende:

X objX = (X)Activator.CreateInstance(dynamicType);
int intNumber = objX.Number(4);


Mvh.

- Snap :)
Avatar billede decrypto Nybegynder
14. marts 2007 - 12:43 #22
Ok lyder godt.....
lige ser min klasse således ud:
-------------------------------------------

namespace ClassFactory
{
    public class ClassBuilder
    {
        public void BuildClass()
        {
            string src = @"

                public class ProductA
                {
                    public ProductA(){}
                           
                    public override string ToString()
                    {
                        return ""I am a X"";
                    }

                    public string GetMessage()
                    {
                        return ""I am a ProductA"";
                    }
                }
                ;";

            CodeDomProvider compiler = CodeDomProvider.CreateProvider("CSharp");
            CompilerParameters param = new CompilerParameters();
           
            param.GenerateInMemory = true;
            param.ReferencedAssemblies.Add("System.dll");
           
            CompilerResults result = compiler.CompileAssemblyFromSource(param, src);
            Assembly asembly = result.CompiledAssembly;

            object obj = asembly.CreateInstance("ProductA");
            Console.WriteLine(obj);
           
        }
    }
}
Avatar billede decrypto Nybegynder
14. marts 2007 - 14:05 #23
Udover det så ville det jo være rarest ikke at caste til x klassen. Min formodning vil være at dem der bruger / instansierer klassen, ikke ved hvilen type klasse det er.
Avatar billede arne_v Ekspert
14. marts 2007 - 15:13 #24
Der er ikke meget pointe i at generere dynamisk kode, hvis kalder skal kende klassen.

Du har 2 muligheder:

1)  kalde metoder via reflection som i hmortensens eksempel

2)  lade alle dine dynamisk genrerede klasser implementere et interface
    eller en abstrakt basis klasse og saa caste til den
Avatar billede arne_v Ekspert
14. marts 2007 - 15:18 #25
og et svar fra mig
Avatar billede decrypto Nybegynder
14. marts 2007 - 15:33 #26
Mener du at der ikke er ide i at generere dynamisk, hvis kalderen IKKE kender klassen?

For det er den formodning jeg vil have, at han ikke gør. Kigger lige på eksemplerne derhjemme....
Avatar billede arne_v Ekspert
14. marts 2007 - 15:40 #27
nej - der er ikke nogen ide hvis kalderen skal kende - hvis han ikke kender den er der en ide i det
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