Wątek zablokowany 2013-05-06 20:44 przez somekind.

System refleksji i wywołanie fragmentu kodu

0

Witam
Jest możliwośc wywołania fragmentu kodu który przekażemy jako string. Chodzi mi o coś takiego:

 
 public string Metod(string functionName)
        {
            Type t = this.GetType();
            MethodInfo method = t.GetMethod(functionName);
            return (string)method.Invoke(this, null);
            // Could also be return (int)result;, if it was an integer (boxed to an object), etc.
        }

tylko ze zamiast przekazać nazwę funkcji to przekazać fragmento kodu np: "MessageBox.Show("Olek");"

0

Nie znam się na C#, ale ten przykład, który dałeś, na pewno nie zadziała. Powód?

"MessageBox.Show("Olek");"

Zobacz kolory. String jest oznaczany na szaro, więc słowo "Olek" nie jest stringiem. W tym miejscu zwróci ci się błąd.

Co do reszty, nie jestem pewny, ale chyba nie.

0

Musiałbyś zapewne wykonać coś w rodzaju mini-parsera.
Czyli wydobyć np.z tego rzeczonego "MessageBox.Show(\"Olek\");" nazwę klasy i metody oraz parametry, a potem porobić czarną-magię i to uruchomić.
Ale po cokolwiek chcesz to robić, robisz to źle i zapewne masz błąd na poziomie logiki aplikacji.

0

To nie jest fragment kodu który probowalem wykonac. W kodzie jest napisane ze trzeba podać nazwe funklcji a ja chce wykonać fragment kody który jest w stringu

moze byc np: "for(int i = 0 ; i< 10 ; i++){ a += i 1 }".

3

Wszystko się da:

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

namespace RunEverything
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Witaj w dziwnym programie!");
                
            Eval(@"System.Windows.Forms.MessageBox.Show(""Olek"")");

            Console.ReadLine();
        }

        static void Eval(string code)
        {
            string pattern = @"namespace N {{ public class C {{ public static void M() {{ {0}; }} }} }}";
            string source = string.Format(pattern, code);

            CSharpCodeProvider provider = new CSharpCodeProvider();
            CompilerParameters parameters = new CompilerParameters()
            {
                GenerateExecutable = false,
                GenerateInMemory = true,
            };
            parameters.ReferencedAssemblies.Add("System.dll");
            parameters.ReferencedAssemblies.Add("System.Windows.Forms.dll");

            CompilerResults compilerResult = provider.CompileAssemblyFromSource(parameters, source);

            Assembly assembly = compilerResult.CompiledAssembly;
            Type type = assembly.GetType("N.C");
            MethodInfo method = type.GetMethod("M");

            method.Invoke(null, null);
        }
    }
}

Chociaż ja bym wolał to zrobić tak:

using System;
using System.Windows.Forms;

namespace RunEverything
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Witaj w dziwnym programie!");

            Eval(() => MessageBox.Show("Olek"));

            Console.ReadLine();
        }

        private static void Eval(Action action)
        {
            action.Invoke();
        }
    }
}
0

Witam a jakbym chciał dać cały kod programu?? i żeby przekompilował i wykonał??

0

Jest to jak najbardziej możliwe, o ile kod będzie poprawny oraz ustawisz wszystkie CompilerParameters i dodasz odpowiednie ReferencedAssembllies.

0

A nie ma jakiegoś gotowego rozwiązania?? pododawałem CompilerParameters i ReferencedAssembllies ale zawsze jak wkleje kod programu to sie sypie bo brakuje czegoś albo coś. I jak sie pozbyć by nie trzeba było dodawać całej struktury np System.Windows.Forms.MessageBox.Show(""Olek"") tylko samo MessaheBoxShow coś tam coś....

0

Masz bardzo dziwaczny problem.
Sądzę, że problem leży w logice programu.

Na Twój problem pewnie wystarczy zwykły delegat.

0
quatron napisał(a):

A nie ma jakiegoś gotowego rozwiązania?? pododawałem CompilerParameters i ReferencedAssembllies ale zawsze jak wkleje kod programu to sie sypie bo brakuje czegoś albo coś. I jak sie pozbyć by nie trzeba było dodawać całej struktury np System.Windows.Forms.MessageBox.Show(""Olek"") tylko samo MessaheBoxShow coś tam coś....

A using w tym kodzie jest?

0
quatron napisał(a):

A nie ma jakiegoś gotowego rozwiązania?? pododawałem CompilerParameters i ReferencedAssembllies ale zawsze jak wkleje kod programu to sie sypie bo brakuje czegoś albo coś. I jak sie pozbyć by nie trzeba było dodawać całej struktury np System.Windows.Forms.MessageBox.Show(""Olek"") tylko samo MessaheBoxShow coś tam coś....

Dodać using w kodzie.
Błędy kompilacji masz we właściwości Errors klasy CompilerResults.

A jeśli faktycznie nie dajesz rady skompilować swojego kodu, to może pokaż go tutaj, poszukamy błędów.

0
 static void Execute(string code)
        {
            
            string source = string.Format(code);

            CSharpCodeProvider provider = new CSharpCodeProvider();
            CompilerParameters parameters = new CompilerParameters()
            {
                GenerateExecutable = false,
                GenerateInMemory = true,
            };
            parameters.ReferencedAssemblies.Add("System.dll");
            parameters.ReferencedAssemblies.Add("System.Windows.Forms.dll");
            parameters.ReferencedAssemblies.Add("System.Core.dll");
	    parameters.ReferencedAssemblies.Add("System.Data.dll");
            parameters.ReferencedAssemblies.Add("System.Data.Linq.dll");
            parameters.ReferencedAssemblies.Add("System.DirectoryServices.dll");
            parameters.ReferencedAssemblies.Add("System.Configuration.dll");
            parameters.ReferencedAssemblies.Add("System.Web.dll");
            parameters.ReferencedAssemblies.Add("System.Xml.dll");
            parameters.ReferencedAssemblies.Add("System.Windows.Forms.dll");
            parameters.ReferencedAssemblies.Add("System.Web.Services.dll");
            parameters.ReferencedAssemblies.Add("System.ServiceModel.dll");
            parameters.ReferencedAssemblies.Add("System.IdentityModel.dll");

            CompilerResults compilerResult = provider.CompileAssemblyFromSource(parameters, source);

            Assembly assembly = compilerResult.CompiledAssembly;
            Type type = assembly.GetType("N.C");
            MethodInfo method = type.GetMethod("M");

            method.Invoke(null, null);

        }

Taki kod a chce wykonać podczas działania już aplikacji np taki kod:

public class Program
{
static int Main()
{
MessageBox.Show("nwecnbcoeiw");
return 0;
}
}
Chdzi mi o większe rzeczy ale na poczatek chce żeby proste programiki typu wyświetl, zmień kolor tła Forma działały tzn wykonywały sie w trakcie działania juz aplikacji.

0
quatron napisał(a)

I jak sie pozbyć by nie trzeba było dodawać całej struktury np System.Windows.Forms.MessageBox.Show(""Olek"") tylko samo MessaheBoxShow coś tam coś....

somekind napisał(a)

Dodać using w kodzie.

quatron napisał(a)

Taki kod a chce wykonać podczas działania już aplikacji np taki kod:

public class Program
{
    static int Main()
    {
        MessageBox.Show("nwecnbcoeiw");
        return 0;
    }
}

A gdzie using?

0

Dodałem using nawet żeby sie nie bawić w przejrzystą strukture programu chce wykonać kod który jest w 1 stringu

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Diagnostics;using System.Text;using System.IO;using System.Threading.Tasks;using System.Windows.Forms;using System.Text.RegularExpressions;using System.CodeDom.Compiler;using System.Reflection;using Microsoft.CSharp;public class Program{static int Main(){MessageBox.Show("nwecnbcoeiw");return 0;}}

to woła że Input string was not in a correct format. Czyli jak wczytać ten kod żeby został dobrze obsłużony...

0

Ten kod nie ma deklaracji przestrzeni nazw dla klasy Program. Brakuje tutaj \ przed ".
Nie wiem czy tak robiłeś, ale lepiej mieć kod testowy wcześniej przygotowany w IDE i sprawdzony - później przeklejony i oczywiście przerobiony (\ przed "). Proponuję Tobie do testowania wczytywać kod z pliku - będzie wygodniej

0

A jak mam wykonać w programie kod wczytany??
Jak on Od razu przyjmuje string...

static void Execute(string code)
        {

           string source = string.Format(code);

            CSharpCodeProvider provider = new CSharpCodeProvider();
            CompilerParameters parameters = new CompilerParameters()
            {
                GenerateExecutable = false,
                GenerateInMemory = true,
            };
            parameters.ReferencedAssemblies.Add("System.dll");
            parameters.ReferencedAssemblies.Add("System.Windows.Forms.dll");
            parameters.ReferencedAssemblies.Add("System.Core.dll");
            parameters.ReferencedAssemblies.Add("System.Data.dll");
            parameters.ReferencedAssemblies.Add("System.Data.Linq.dll");
            parameters.ReferencedAssemblies.Add("System.DirectoryServices.dll");
            parameters.ReferencedAssemblies.Add("System.Configuration.dll");
            parameters.ReferencedAssemblies.Add("System.Web.dll");
            parameters.ReferencedAssemblies.Add("System.Xml.dll");
            parameters.ReferencedAssemblies.Add("System.Windows.Forms.dll");
            parameters.ReferencedAssemblies.Add("System.Web.Services.dll");
            parameters.ReferencedAssemblies.Add("System.ServiceModel.dll");
            parameters.ReferencedAssemblies.Add("System.IdentityModel.dll");

            CompilerResults compilerResult = provider.CompileAssemblyFromSource(parameters, source);

            Assembly assembly = compilerResult.CompiledAssembly;
            Type type = assembly.GetType("N.C");
            MethodInfo method = type.GetMethod("M");

            method.Invoke(null, null);


        }

Wczytuje tak:

string nazwaPliku;
            OpenFileDialog okienko = new OpenFileDialog();
            okienko.Filter = "(cs)|*.cs";
            if (okienko.ShowDialog() == DialogResult.OK)
            {
                nazwaPliku = okienko.FileName;
                StreamReader czytaj = new StreamReader(nazwaPliku);
                nazwaPliku = czytaj.ReadToEnd();
                Execute(nazwaPliku);
            }
0

A jak mam wykonać w programie kod wczytany??
Jak on Od razu przyjmuje string...

Nie rozumiem pytania. string to string, a czy wklepany w kodzie, czy wczytany z pliku to tutaj nie ma znaczenia. Zresztą widzę, że kod wczytujesz z pliku do stringa więc o co chodzi?

A to do czego?:

string source = string.Format(code);
0

ups nie zauważyłem tego że to zostało już poprawione.
Wczytuje taki kod

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

namespace N
{
    class C
    {
        public static void M()
        {
            int a = 20;
	    int b = 50;
	    int c = a + b;
            MessageBox.Show("aaaa:" + c);
        }

        
    }
}

To wywala mi sie na tej linijce
Assembly assembly = compilerResult.CompiledAssembly;
Taki błąd...
Could not load file or assembly 'file:///C:\Users\XXX\AppData\Local\Temp\ncljuwni.dll' or one of its dependencies.

0

Nie działa, bo kod, który wczytujesz się nie kompiluje. Serio komunikat: "The name 'MessageBox' does not exist in the current context" nic Ci nie mówi? o.O

Ogólnie wątki na forum pozostawiamy otwarte po to, aby coś jeszcze móc uściślić, dopisać w nich coś konstruktywnego albo podać lepszy sposób rozwiązania. Na pewno nie po to, aby doklejać się do nich z kolejnymi problemami.
@quatron, jeśli jeszcze będziesz miał problem, to załóż nowy wątek, ten zamykam.

1 użytkowników online, w tym zalogowanych: 0, gości: 1