Article View: alt.pl.comp.lang.csharp
Article #21754Re: jak to sie robi w C# ?
From: Selvin
Date: Mon, 20 Sep 2010 22:38
Date: Mon, 20 Sep 2010 22:38
130 lines
6701 bytes
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-mailReferences:
<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