🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: alt.pl.comp.lang.csharp
Article #21754

Re: jak to sie robi w C# ?

#21754
From: Selvin
Date: Mon, 20 Sep 2010 22:38
130 lines
6701 bytes
ciach z nudow pobawilem sie jeszcze:
1. wywalilem MEF(byl tylko po to by nie bawic sie Reflection)
2. w teorii (http://bloggingabout.net/blogs/vagif/archive/2010/04/02/
don-t-use-activator-createinstance-or-constructorinfo-invoke-use-
compiled-lambda-expressions.aspx) (i tam jest o konstruktorach,
ale ...) uzylem skompilowanego wyrazenia lambda a nie MethodInfo
Invoke (przy duzej ilosci odwolan do tego samego skryptu compilacja
powinna sie zwrocic, zreszta ... nie ma co optymalizowac na sile
trzeba zrobic testy na prawdziwych danych)
3. Exception o nie udanej kompilacji zwraca teraz blad opis i numer
kolumny w ktorej blad wystapil
4. do wysylanego parametru mozna dodac spokojnie funkcje przyklad:
MojaFunkcjaDoPodwajania
5. przyklad wywolania funkcji systemowych (DateTime.Now)
6. zmienilem klase opakowujaca IDataRecord teraz zamias wlasnej klasy
mamy po prostu obiekt typu ExpandoObject uzyskany przez uzycie
rozszerzenia do IDataRecord o nazwie AsDynamic

public static class ScriptProvider
{
    static Regex expr = new Regex("\\s+",
System.Text.RegularExpressions.RegexOptions.Compiled);
    static Dictionary<string, Func<dynamic, dynamic>> scriptscache =
new Dictionary<string, Func<dynamic, dynamic>>();
    const string body = @"using System;public class ScriptType{{public
static object RunScript(dynamic _){{return {0} ;}}}}";
    static int codebegin = body.IndexOf("{0}") - 2;
    static Microsoft.CSharp.CSharpCodeProvider csProvider = new
Microsoft.CSharp.CSharpCodeProvider();
    static CompilerParameters options = new CompilerParameters();
    static ParameterExpression param =
Expression.Parameter(typeof(object), "param");

    static ScriptProvider()
    {
        options.GenerateExecutable = false;
        options.GenerateInMemory = true;
        options.ReferencedAssemblies.Add("System.Core.dll");
        options.ReferencedAssemblies.Add("Microsoft.CSharp.dll");
    }

    static Func<dynamic, dynamic> CreateScript(string code)
    {
        code = expr.Replace(code, string.Empty);
        if (!scriptscache.ContainsKey(code))
        {
            CompilerResults result =
csProvider.CompileAssemblyFromSource(options, string.Format(body,
code));
            if (result.Errors.HasErrors)
            {
                throw new Exception(string.Join(Environment.NewLine,
result.Errors.Cast<CompilerError>().Select(x => string.Format("({1},
{2}), error {3}: {0}", x.ErrorText, x.Line, x.Column - codebegin,
x.ErrorNumber)).ToArray()));
            }
            scriptscache[code] = (Func<dynamic,
object>)Expression.Lambda(typeof(Func<dynamic, object>),
Expression.Call(result.CompiledAssembly.GetType("ScriptType").GetMethod("RunScript"),
param), param).Compile();
        }
        return scriptscache[code];
    }

    public static object RunScript(string code, dynamic param)
{ return CreateScript(code)(param); }
    public static T RunScript<T>(string code, dynamic param) { return
(T)CreateScript(code)(param); }
    public static Func<dynamic, object> GetScriptAsFunction(string
code) { return CreateScript(code); }
}

public static class DataRecordExtensions
{
    public static dynamic AsDynamic(this IDataRecord record)
    {
        ExpandoObject ret = new ExpandoObject();
        IDictionary<string, object> dic = ret as IDictionary<string,
object>;
        for (int i = 0; i < record.FieldCount; i++)
            dic[record.GetName(i)] = record[i];
        return ret;
    }
}

        private void button1_Click(object sender, EventArgs e)
        {
            var csb = new SqlConnectionStringBuilder();
            csb.IntegratedSecurity = true;
            csb.DataSource = ".\\SQLEXPRESS";
            using (var con = new SqlConnection(csb.ConnectionString))
            {
                con.Open();
                var cmd = new SqlCommand(@"SELECT 2.0 iIle, 2.55
dNorma, 120.57 dCena, 0.2 dWsp, '_.iIle * _.dNorma * _.dCena * (1 -
_.dWsp)' sFormula
                UNION ALL
                SELECT 2, 2.55, 120.57, 0.21, '_.iIle * _.dNorma
*       _.dCena * (1 - _.dWsp)'
                UNION ALL
                SELECT 2, 2.55, 120.57, 0.21,
'_.MojaFunkcjaDoPodwajania(_.iIle*_.dNorma*_.dCena*(1-_.dWsp))'
                UNION ALL
                SELECT 2 , 2 , 120 , 0 , 'DateTime.Now.Day* _.iIle*
_.dNorma * _.dCena * (1 - _.dWsp)'", con);
                //ostatnia funkcje uzaleznilismy takze od dnia
                using (var reader = cmd.ExecuteReader())
                {
                    while (reader.Read())
                    {
                        dynamic param = reader.AsDynamic();
                        // a co tam dodamy swoja funkcje
                        param.MojaFunkcjaDoPodwajania = new
Func<dynamic, object>(x => 2 * x);
                        try
                        {
                            var result =
ScriptProvider.RunScript<decimal>(param.sFormula, param);
                            MessageBox.Show(string.Format("{0} = >
{1}", param.sFormula, result));
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show(ex.Message, "Błąd",
MessageBoxButtons.OK, MessageBoxIcon.Error);
                        }
                    }
                }
            }
        }
Technical Details
Message-ID: <586ce832-b369-4b9c-93f8-789982488be4@j5g2000vbg.googlegroups.com>
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.icm.edu.pl!plix.pl!newsfeed1.plix.pl!goblin1!goblin.stu.neva.ru!postnews.google.com!j5g2000vbg.googlegroups.com!not-for-mail
References: <4c9721da$0$27026$65785112@news.neostrada.pl> <29a54593-9d92-4968-ba75-062ef28bbe4f@m1g2000vbh.googlegroups.com> <679459a9-2df4-4fe8-b574-72f0024da8f8@g10g2000vbc.googlegroups.com>

Show Full Headers
Complete Article Headers
Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!news.icm.edu.pl!plix.pl!newsfeed1.plix.pl!goblin1!goblin.stu.neva.ru!postnews.google.com!j5g2000vbg.googlegroups.com!not-for-mail
From: Selvin <przemek.sulikowski@gmail.com>
Newsgroups: alt.pl.comp.lang.csharp
Subject: Re: jak to sie robi w C# ?
Date: Mon, 20 Sep 2010 15:38:39 -0700 (PDT)
Organization: http://groups.google.com
Lines: 131
Message-ID: <586ce832-b369-4b9c-93f8-789982488be4@j5g2000vbg.googlegroups.com>
References: <4c9721da$0$27026$65785112@news.neostrada.pl> <29a54593-9d92-4968-ba75-062ef28bbe4f@m1g2000vbh.googlegroups.com> <679459a9-2df4-4fe8-b574-72f0024da8f8@g10g2000vbc.googlegroups.com>
NNTP-Posting-Host: 79.186.251.223
Mime-Version: 1.0
X-Trace: posting.google.com 1285022319 21074 127.0.0.1 (20 Sep 2010 22:38:39 GMT)
X-Complaints-To: groups-abuse@google.com
NNTP-Posting-Date: Mon, 20 Sep 2010 22:38:39 +0000 (UTC)
Complaints-To: groups-abuse@google.com
Injection-Info: j5g2000vbg.googlegroups.com; posting-host=79.186.251.223; posting-account=R8EpSwoAAADeCYcG96LM5BAc_tdIdesQ
User-Agent: G2/1.0
X-HTTP-UserAgent: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/534.3 (KHTML, like Gecko) Chrome/6.0.472.59 Safari/534.3,gzip(gfe)
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit