Avatar billede kak Nybegynder
27. juli 2006 - 12:33 Der er 35 kommentarer og
1 løsning

Køre sub via database

Pga. hyppige ændringer, vil jeg gerne hente koden til en sub fra en database.

Men kan det lade sig gøre, og hvordan får jeg så afviklet koden, efter jeg har hentet den?
Avatar billede snepnet Nybegynder
27. juli 2006 - 12:49 #1
Der er et tilsvarende spørgsmål her:
http://www.eksperten.dk/spm/721059
Mvh
Avatar billede kak Nybegynder
27. juli 2006 - 13:21 #2
Kring fik det jo desværre ikke til at virke, men det skal også være VB kompilering. Har du evt. et link til hvordan det gøres med VB?
Avatar billede arne_v Ekspert
27. juli 2006 - 13:49 #3
Avatar billede arne_v Ekspert
27. juli 2006 - 13:50 #4
Avatar billede arne_v Ekspert
27. juli 2006 - 13:50 #5
Avatar billede arne_v Ekspert
27. juli 2006 - 13:52 #6
Avatar billede kak Nybegynder
27. juli 2006 - 14:51 #7
Tak for det. Jeg kigger lige på de forskellige links, og vender tilbage.
Avatar billede arne_v Ekspert
29. juli 2006 - 23:51 #8
jeg tror faktisk at det første link er mest relevant for din problem stilling
Avatar billede kak Nybegynder
03. august 2006 - 15:48 #9
Jeg har haft lidt travlt, men endelig fået kigget på det.

Jeg går ud fra, at du mente denne har var mest relevant: http://www.codeproject.com/vb/net/DotNetCompilerArticle.asp

Men så vidt jeg lige kan gennemskue, bruger den bl.a et par .dll, og jeg skal jo være sikker på, at det virker alle steder (jeg ved godt at koden bliver kompileret på serveren, men det skal helst virke, uden at jeg skal installere noget på serveren).

Kan koden køres fra en .aspx side, eller er det mere en .exe, beskrivelsen henviser til?

Det er et almindeligt website, hvorfra jeg gerne vil hente en sub i en database, og eksekvere den.

Beklager hvis dine links forklarer det, men jeg synes ikke jeg kan gennemskue det, så jeg håber du kan hjælpe mig lidt videre :-)
Avatar billede arne_v Ekspert
03. august 2006 - 16:07 #10
ja

den compiler noget kode fra en string til en in memory assembly hvordi man kan
kalde koden

den kraver kun standard .NET

teknikken kan bruges i enhver form for .NET apps inkl. ASP.NET

du skal angive en reference til de DLL'er som den kode du compiler dynamisk skal bruge

men det er jo ret naturligt

skal koden ikke bruge nogle DLL'er saa skal der ikke angives nogen
Avatar billede arne_v Ekspert
03. august 2006 - 16:22 #11
en meget simpel code snippet:

            Dim src As String = "Public Class X" & Environment.NewLine & "    Public Overloads Overrides Function ToString() As String" & Environment.NewLine & "        return ""I am a X""" & Environment.NewLine & "    End Function" & Environment.NewLine & "End Class"
            Dim comp As ICodeCompiler = (New VBCodeProvider).CreateCompiler
            Dim param As CompilerParameters = New CompilerParameters
            param.GenerateInMemory = True
            param.ReferencedAssemblies.Add("System.dll")
            Dim res As CompilerResults = comp.CompileAssemblyFromSource(param, src)
            Dim asm As System.Reflection.Assembly = res.CompiledAssembly
            Dim o As Object = asm.CreateInstance("X")
            Console.WriteLine(o)
Avatar billede kak Nybegynder
04. august 2006 - 13:44 #12
Jeg har prøvet med dette her:

            Dim provider As Microsoft.VisualBasic.VBCodeProvider
            Dim compiler As System.CodeDom.Compiler.ICodeCompiler

            provider = New Microsoft.VisualBasic.VBCodeProvider

            Dim strCode As String
            strCode = "lbltest.text=xxx"
            'Dim src As String = "Public Class X" & Environment.NewLine & "    Public Overloads Overrides Function ToString() As String" & Environment.NewLine & "        return ""I am a X""" & Environment.NewLine & "    End Function" & Environment.NewLine & "End Class"
            Dim src As String = "Public Class X" & Environment.NewLine & "    Public Function doMyGrid()" & Environment.NewLine & strCode & Environment.NewLine & " return ""I am a X""" & Environment.NewLine & "    End Function" & Environment.NewLine & "End Class"
            Dim comp As CodeDom.Compiler.ICodeCompiler = provider.CreateCompiler
            Dim param As CodeDom.Compiler.CompilerParameters = New CodeDom.Compiler.CompilerParameters
            param.GenerateInMemory = True
            param.ReferencedAssemblies.Add("System.dll")
            Dim res As CodeDom.Compiler.CompilerResults = comp.CompileAssemblyFromSource(param, src)
            Dim asm As System.Reflection.Assembly = res.CompiledAssembly
            Dim o As Object = asm.CreateInstance("X")
            VBmsg(o.domygrid)

Men så fejler på, at den ikke kan finde en dll-fil. Navnet på dll'en er fra mit temp-dir og altid nye navne, så jeg gætter på, det er en den opretter runtime.
Hvis jeg fjernes strCode, virker det fint.

Hvordan kan jeg få den til at køre andet end at returnere et tekst?

Jeg skal i princippet ikke have den til at returnere noget, så det må også gerne være en sub. Men det gav samme fejl, da jeg ændrede koden til det.
Avatar billede arne_v Ekspert
05. august 2006 - 01:09 #13
jeg undrer mig over hvordan det kan compile ?

lbltest.text=xxx i class X er da ikke valid kode

måske jeg skulle have tilføjet den kode som udskriver compiler fejl ...
Avatar billede kak Nybegynder
05. august 2006 - 13:47 #14
Ok, jeg kan godt se, at xxx selvfølgelig ikke indeholder en værdi. Men denne her virker heller ikke:
strCode = "lbltest.BackColor = Drawing.Color.Red"

Der er naturligvis en label der hedder lbltest og det virker fint, hvis jeg hardcoder den linie.

Men jeg vil jo netop gerne kunne lave forskellige ting via den kode, jeg henter i en database.
Avatar billede arne_v Ekspert
05. august 2006 - 16:30 #15
du laver en nye class X - koden i den kører i dens kontekst - ikke i den nuværende
klasses kontekst

hvis du skal have noget over til X skal det sende som argument til metoden

(så skal du enten implementere et interface eller over i reflection men ...)
Avatar billede kak Nybegynder
05. august 2006 - 18:21 #16
Så kan jeg vel ikke opnå det jeg gerne vil, eller hvad?

Lad mig lige forklare det hele..... Jeg har en side med et gridview, der automatisk genererer kolonner. Jeg lægger så sql-sætninger i en db, henter den ønskede sql og databinder mit gridview på den. Så langt så godt.

Det jeg også gerne vil, er at have mulighed for at lave yderligere behandling af mit gridview, efter der er lagt data i det. Det kunne f.eks. være formattering af bestemte kolonner, eller summering af et talfelt.

Kan jeg opnå det, men en kode som jeg henter fra databasen?
Avatar billede arne_v Ekspert
05. august 2006 - 19:02 #17
det vil jeg da tro

jeg kan prøve at lave et eksempel senere idag
Avatar billede arne_v Ekspert
06. august 2006 - 03:26 #18
prøv og studer det her eksempel:

Imports System
Imports System.CodeDom.Compiler
Imports Microsoft.VisualBasic

Namespace E
    Public Interface IDoer
        Sub DoIt(app As MainClass)
    End Interface
    Public Class MainClass
        Public Sub ItWorks
            Console.WriteLine("Det virker")
        End Sub
        Public Sub RealMain()
            Dim src As String = "Imports E" & Environment.NewLine & _
                                "Public Class X" & Environment.NewLine & _
                                "    Implements IDoer" & Environment.NewLine & _
                                "    Public Sub DoIt(app As MainClass) Implements IDoer.DoIt" & Environment.NewLine & _
                                "        app.ItWorks" & Environment.NewLine & _
                                "    End Sub" & Environment.NewLine & _
                                "End Class"
            Dim comp As ICodeCompiler = (New VBCodeProvider).CreateCompiler
            Dim param As CompilerParameters = New CompilerParameters
            param.GenerateInMemory = True
            param.ReferencedAssemblies.Add("System.dll")
            param.ReferencedAssemblies.Add(System.Reflection.Assembly.GetExecutingAssembly().Location)
            Dim res As CompilerResults = comp.CompileAssemblyFromSource(param, src)
            Dim comperr As CompilerError
            For Each comperr In res.Errors
                Console.WriteLine(comperr)
            Next
            Dim asm As System.Reflection.Assembly = res.CompiledAssembly
            Dim o As IDoer = CType(asm.CreateInstance("X"), IDoer)
            o.DoIt(me)
        End Sub
        Public Shared Sub Main(ByVal args As String())
            Dim main As MainClass = New MainClass
            main.RealMain
        End Sub
    End Class
End Namespace
Avatar billede arne_v Ekspert
06. august 2006 - 03:26 #19
det er en console app og ikke en web app men det skulle ikke betyde noget
Avatar billede kak Nybegynder
07. august 2006 - 20:36 #20
jeg har forsøgt at få det til at virke, men kan ikke få det integreret med min nuværende kode.

Jeg har lavet en ny class fil (mainclass.vb) og placeret din kode i den. Jeg tilføjer så <add namespace="mainclass"/> i web.config, men jeg kan ikke kalde noget fra din kode.

Skal jeg kalde main eller realmain?

Jeg har også prøvet det samme, men lavet en E.vb og tilføjet <add namespace="E"/> i stedet, men det kan jeg stadig ikke kalde.
Avatar billede kak Nybegynder
13. august 2006 - 14:40 #21
arne_v, kan du fortælle om jeg skal kalde main eller realmain, og hvordan det gøres?
Avatar billede arne_v Ekspert
15. august 2006 - 02:44 #22
du skal bare kalde den metode hvor din kompilerende kode er formentligt noget
i din Page da du jo gerne vil tilgå nogle kontroller på den

jeg lave det på den måde for at kalde en ikke shared metode da jeg skulle
illustere hvordan man sender me med over
Avatar billede kak Nybegynder
15. august 2006 - 18:29 #23
Du må undskylde hvis jeg er helt umulig at forklare det til, men kan du skære det ud i pap for mig? Helt præcis, hvordan kan jeg gøre det?
Avatar billede arne_v Ekspert
16. august 2006 - 04:04 #24
jeg har prøvet at konvertere det til ASP.NET/VB.NET kontekst
Avatar billede arne_v Ekspert
16. august 2006 - 04:04 #25
<%@ Page Language="VB" Inherits="E.DynCompiler" %>
<asp:label id="dynstuff" runat="server"/>
Avatar billede arne_v Ekspert
16. august 2006 - 04:04 #26
Imports System
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports System.CodeDom.Compiler
Imports Microsoft.VisualBasic

Namespace E
    Public Interface IDoer
        Sub DoIt(app As DynCompiler)
    End Interface
    Public Class DynCompiler
    Inherits Page
        Protected dynstuff As Label
        Public Sub SetDynstuff(s As String)
            dynstuff.Text = s
        End Sub
        Public Sub Page_Load(Sender As Object, E As EventArgs)
            Dim src As String = "Imports E" & Environment.NewLine & _
                                "Public Class X" & Environment.NewLine & _
                                "    Implements IDoer" & Environment.NewLine & _
                                "    Public Sub DoIt(app As DynCompiler) Implements IDoer.DoIt" & Environment.NewLine & _
                                "        app.SetDynstuff(""Det virker"")" & Environment.NewLine & _
                                "    End Sub" & Environment.NewLine & _
                                "End Class"
            Dim comp As ICodeCompiler = (New VBCodeProvider).CreateCompiler
            Dim param As CompilerParameters = New CompilerParameters
            param.GenerateInMemory = True
            param.ReferencedAssemblies.Add("System.dll")
            param.ReferencedAssemblies.Add("System.Web.dll")
            param.ReferencedAssemblies.Add(System.Reflection.Assembly.GetExecutingAssembly().Location)
            Dim res As CompilerResults = comp.CompileAssemblyFromSource(param, src)
            Dim asm As System.Reflection.Assembly = res.CompiledAssembly
            Dim o As IDoer = CType(asm.CreateInstance("X"), IDoer)
            o.DoIt(me)
          End Sub
    End Class
End Namespace
Avatar billede kak Nybegynder
16. august 2006 - 21:11 #27
Tak for det, nu er jeg kommet lidt videre. Jeg kan sagtens får dit eksempel til at virke, men jeg er i tvivl, om jeg kan opnå det jeg gerne vil?!

Jeg er med på, at koden køres via
        Public Sub SetDynstuff(s As String)
            dynstuff.Text = s
        End Sub
og at den kaldes med app.SetDynstuff(""Det virker"")

Men jeg vil jo gerne kunne gøre andet, end at sætte teksten på en label, eller sådan noget i den stil.

Jeg vil f.eks. gerne genngmgå et eksisterende gridview og f.eks. formattere et bestemt kolonne eller lægge tallene fra en kolonne sammen. Koden til det, er dynamisk så hvordan kan jeg få den til at eksekvere det?

Jeg kan jo ikke blot kalde SetDynstuff med hele koden.
Avatar billede arne_v Ekspert
16. august 2006 - 21:26 #28
du kan lave baade X.DoIt og DynCompiler.SetDynStuff saa komplekse som du vil

100 linier

1000 linier

du kan ogsaa kalde flere metoder i den dynamiske klasse

og du kan lade den dynamiske klasse kalde flere metoder i page klassen
Avatar billede kak Nybegynder
16. august 2006 - 22:06 #29
Det er vel ikke helt fleksibelt nok, at bruge den dynamiske klasse, da jeg gerne vil have hele den dynamiske kode i en database, og der kan være utallige forskellige ting, jeg ønsker at køre.

Jeg kan ikke lige gennemskue, hvordan jeg kan bruge x.DoIt til det? Hvordan kan jeg kalde den med en hel række koder?
Avatar billede arne_v Ekspert
17. august 2006 - 03:06 #30
enten gemmer du hele X klassen i databasen eller så gemmer du kun indmaden af DoIt
i databasen

du kan sagtens have forskelligt indhold

du skal bare have alle de metoder i din page klasse som alle de forskellige kode
stumper kan få brug for at kalde
Avatar billede kak Nybegynder
17. august 2006 - 12:19 #31
Hvis jeg nu istedet for at kalde sub'en (SetDynstuff) fra Sub Doit i X klassen, f.eks. ønsker at udføre følgende:

"GridView1.BorderColor = Drawing.Color.DarkRed" Direkte fra Sub Doit, hvordan skal jeg så ændre denne?

Jeg går ud fra at:

app.SetDynStuff(""Det virker"") så skal erstattes med noget andet for direkte at opnå: GridView1.BorderColor = Drawing.Color.DarkRed - men hvad ?

For sætter jeg blot: GridView1.BorderColor = Drawing.Color.DarkRed ind i stedet for app.setdynstuff... så fejler den med det samme...
Avatar billede arne_v Ekspert
18. august 2006 - 02:39 #32
page klasse:

Public Sub SetGridBorderColor(c As Color)
  GridView1.BorderColor = c
End Sub

og i DoIt:

app.SetGridBorderColor(Color.DarkRed)
Avatar billede kak Nybegynder
18. august 2006 - 08:24 #33
Ok. Det er ikke så smidigt som jeg gerne ville have det. Nu skal jeg jo lave en ny sub, for hver eneste ting jeg kan forestille mig der skal laves på mit gridview.

Jeg havde håbet på, at jeg kunne lave min aspx side, og så komme HELE indholdet af en sub i databasen. Alt efter hvilken post i databasen der blev kaldt, kunne jeg så hente og eksekvere den tilhørende sub.

Det ville så være underordnet om den skulle sætte bordercolor, formatere et felt eller noget helt 3.

Vil du oprette et svar, så du kan få point?
Avatar billede kak Nybegynder
18. august 2006 - 10:59 #34
Lige et tillægsspørgsmål...

Det er vel det samme igen - at jeg fra DoIt kalder en anden sub, og ikke foretager ændringen af "bordercolor" DIREKTE i DoIT - men via SetGridBorderColor...

Kan det andet slet ikke lade sig gøre ?
Avatar billede arne_v Ekspert
18. august 2006 - 13:31 #35
hvis de ting du vil ændre er public så behøver du ikke nogen sub i din page class
for at ændre dem

men OOP folket vil jagte dig med økser, hvis du ikke bruger private/protectd fields
og public metoder

og svar
Avatar billede kak Nybegynder
18. august 2006 - 14:39 #36
Tak for hjælpen!
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