
Сообщение от amr-now
Затравка для понимания Expression ))
|
для начало нужно эти "2+2*2" разобрать с такой проблем не будит а вот если туда еще всякие функции
то жу больше проблем, а потом еще и метод написать
которая из этих наборов цифр знаков и функций сам составить выражения это еще сложней насчет компилятора кода изначально такой и использовал

Сообщение от amr-now
Выполнение C# кода "на лету"
|
но потом немного за морочился и сейчас он состоит из 7 классов
возможно тут все можно было проще но писал давненько уже
и не все документированной я уже сам не вспомню что как работает но если интересно вот
Осторожно много кода!!!!!
Кликните здесь для просмотра всего текста
Кликните здесь для просмотра всего текста
| C# | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
| using System.Collections.Generic;
using System.Linq;
using HelpExtensionClass.Extension.CollectionExtension.CollectionNullEqualsExtension;
using HelpExtensionClass.Extension.StringExtension;
using JetBrains.Annotations;
namespace HelpExtensionClass.Macro.CodeGenerator
{
/// <summary>
/// генератор кода класса
/// </summary>
public class CodeClass
{
[UsedImplicitly]
public List<CodeParameter> Parameters { get; } = new List<CodeParameter>();
public List<CodeDelegate> Delegates { get; } = new List<CodeDelegate>();
[UsedImplicitly]
public CodeDelegate Construct
{
get;
}
public CodeClass(string name, string code, string namespaces,
List<CodeParameter> parameters = null,
List<CodeDelegate> delegates = null, string codeConstruct = null, params CodeDelegateParam[] delegateParams)
{
Name = name;
Code = code;
Namespace = namespaces;
if (parameters != null)
Parameters = parameters;
if (delegates != null)
Delegates = delegates;
Construct = new CodeDelegate(Name, codeConstruct, null, delegateParams);
}
private string ClassBootCodeString => FormatClassBoot.Formats(
Construct.DelegateCodeStringConstruct,
Parameters.Select(x => x.ParamsCodeString).ToList().Joins(" "),
Delegates.Select(x => x.DelegateCodeString).ToList().Joins(" "));
private string CodeStringClass => FormatClass.Formats("public", Name, ClassBootCodeString);
public string ClassCodeString => FormatNamespace.Formats(Namespace, CodeStringClass);
[UsedImplicitly]
public string Name
{
get;
}
[UsedImplicitly]
public string Code
{
get;
}
[UsedImplicitly]
public string Namespace
{
get;
}
private const string FormatClassBoot = "{0} {1} {2}";
private const string FormatNamespace = "namespace {0} {{ {1} }}";
private const string FormatClass = "{0} class {1} {{ {2} }}";
}
} |
|
Кликните здесь для просмотра всего текста
| C# | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
| using System;
using System.Collections.Generic;
using System.Linq;
using HelpExtensionClass.Extension.CollectionExtension.CollectionNullEqualsExtension;
using HelpExtensionClass.Extension.ObjectExtension.ObjectNullEqualsExtension;
using HelpExtensionClass.Extension.StringExtension;
namespace HelpExtensionClass.Macro.CodeGenerator
{
/// <summary>
/// Генератор кода делегата
/// </summary>
public class CodeDelegate
{
public List<CodeDelegateParam> CodeDelegateParams { get; } = new List<CodeDelegateParam>();
public string Name
{
get;
}
public string Code
{
get;
}
public Type RetyntType
{
get;
}
public string DelegateCodeString => FormatFunc.Formats("public", RetyntType?.FullName ?? "void", Name,
CodeDelegateParams.Select(x => x.DelegateParamCodeString).ToList().Joins(", "), "", Code ?? "");
public string DelegateCodeStringConstruct => FormatFunc.Formats("public", "", Name,
CodeDelegateParams.Select(x => x.DelegateParamCodeString).ToList().Joins(", "), "", Code ?? "");
public CodeDelegate(string name, string code, Type retynttype = null, params CodeDelegateParam[] paramsParams)
{
Name = name;
Code = code;
RetyntType = retynttype;
if (paramsParams.NotNull())
CodeDelegateParams.AddRange(paramsParams);
}
private const string FormatFunc = "{0} {1} {2}({3}){4} {{ {5} }}";
}
} |
|
Кликните здесь для просмотра всего текста
| C# | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
| using System;
using HelpExtensionClass.Extension.StringExtension;
namespace HelpExtensionClass.Macro
{
public class CodeDelegateParam
{
public CodeDelegateParam(string name, Type type)
{
if (string.IsNullOrEmpty(name))
throw new ArgumentOutOfRangeException(nameof(name));
if (type == null)
throw new ArgumentNullException(nameof(type));
Name = name;
ParameterType = type;
}
public string DelegateParamCodeString => FormatDelegateParam.Formats(ParameterType.FullName, Name);
private const string FormatDelegateParam = "{0} {1}";
public string Name
{
get;
}
public Type ParameterType
{
get;
}
}
} |
|
Кликните здесь для просмотра всего текста
| C# | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
| using System;
using HelpExtensionClass.Extension.ObjectExtension.ObjectNullEqualsExtension;
using HelpExtensionClass.Extension.StringExtension;
using JetBrains.Annotations;
namespace HelpExtensionClass.Macro
{
public class CodeParameter
{
[UsedImplicitly]
public CodeParameter(string name, Type type)
: this(name, type, null)
{
}
public CodeParameter(string name, Type type, object value)
{
if (string.IsNullOrEmpty(name))
throw new ArgumentOutOfRangeException(nameof(name));
if (type.IsNull())
throw new ArgumentNullException(nameof(type));
Name = name;
ParameterType = type;
Value = value;
}
[UsedImplicitly]
public static CodeParameter Create<T>(string name, T value)
=> new CodeParameter(name, typeof(T), value);
public string ParamsCodeString => FormatParams.Formats("public", ParameterType.FullName, Name);
[UsedImplicitly]
public string Name
{
get;
}
[UsedImplicitly]
public Type ParameterType
{
get;
}
[UsedImplicitly]
public object Value
{
get;
}
private const string FormatParams = "{0} {1} {2} {{ get; set; }}";
}
} |
|
Кликните здесь для просмотра всего текста
| C# | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
| using JetBrains.Annotations;
using System;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
namespace HelpExtensionClass.Macro
{
/// <summary>
/// Фабрика делегатов
/// </summary>
public class DelegateTypeFactory
{
private readonly ModuleBuilder _mModule;
public DelegateTypeFactory() => _mModule = AppDomain.CurrentDomain.DefineDynamicAssembly(
new AssemblyName(nameof(DelegateTypeFactory)), AssemblyBuilderAccess.RunAndCollect).DefineDynamicModule(nameof(DelegateTypeFactory));
[UsedImplicitly]
public Type CreateDelegateType(MethodInfo method)
{
if (method?.DeclaringType == null)
throw new ArgumentNullException(nameof(method));
var typeBuilder = CreateBuilder(method);
var invokeMethod = MethodBuilder(typeBuilder, method);
foreach (var parameterInfo in method.GetParameters())
invokeMethod.DefineParameter(parameterInfo.Position, ParameterAttributes.None, parameterInfo.Name);
return typeBuilder.CreateType();
}
private const MethodAttributes MethodBuilderAttributes = MethodAttributes.HideBySig | MethodAttributes.Virtual | MethodAttributes.Public;
private const MethodAttributes ConstructorBuilderAttributes = MethodAttributes.RTSpecialName | MethodAttributes.HideBySig | MethodAttributes.Public;
private static MethodBuilder MethodBuilder(TypeBuilder typeBuilder, MethodInfo method)
{
var ret = typeBuilder.DefineMethod("Invoke", MethodBuilderAttributes,
method.ReturnType, method.GetParameters().Select(p => p.ParameterType).ToArray());
ret.SetImplementationFlags(MethodImplAttributes.CodeTypeMask);
return ret;
}
private static void ConstructorBuilder(ref TypeBuilder typeBuilder) => typeBuilder.DefineConstructor(ConstructorBuilderAttributes,
CallingConventions.Standard, new[] { typeof(object), typeof(IntPtr) }).SetImplementationFlags(MethodImplAttributes.CodeTypeMask);
private TypeBuilder CreateBuilder(MethodInfo method)
{
var typeBuilder = _mModule.DefineType(GetUniqueName($"{method.DeclaringType?.Name}{method.Name}"),
TypeAttributes.Sealed | TypeAttributes.Public, typeof(MulticastDelegate));
ConstructorBuilder(ref typeBuilder);
return typeBuilder;
}
public static Delegate CreateDelegate(object instance, MethodInfo method) => Delegate.CreateDelegate(
new DelegateTypeFactory().CreateDelegateType(method), instance, method);
public static Delegate CreateDelegate(object instance, string method) => CreateDelegate(instance, instance?.GetType().GetMethod(method));
private string GetUniqueName(string nameBase)
{
var number = 2;
var name = nameBase;
while (_mModule.GetType(name) != null)
name = nameBase + number++;
return name;
}
}
} |
|
Кликните здесь для просмотра всего текста
| C# | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
| using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using HelpExtensionClass.Extension.CollectionExtension.CollectionNullEqualsExtension;
using HelpExtensionClass.Extension.ObjectExtension.ObjectNullEqualsExtension;
using HelpExtensionClass.Macro.CodeGenerator;
using JetBrains.Annotations;
using Microsoft.CSharp;
namespace HelpExtensionClass.Macro
{
/// <summary>
/// Компилятор C# кода
/// компилятор формул
/// </summary>
[UsedImplicitly]
public class FormulList
{
[UsedImplicitly]
public List<CodeParameter> Parameters = new List<CodeParameter>();
[UsedImplicitly]
public List<CodeDelegate> Delegates { get; } = new List<CodeDelegate>();
/// <summary>
/// список подключаемых библеотек
/// </summary>
[UsedImplicitly]
public List<string> UsingAssemblies { get; } = new List<string> { "System.dll" };
/// <summary>
/// компилятор
/// </summary>
/// <param name="code"></param>
/// <param name="assemblies"></param>
/// <returns></returns>
private Assembly Compiled(string code, ICollection<string> assemblies = null)
{
var results = new CSharpCodeProvider().CompileAssemblyFromSource(CompilerParameters(assemblies), code);
if (results.Errors.HasErrors)
throw new ArgumentException(FormatErrors(results));
return results.CompiledAssembly;
}
private CompilerParameters CompilerParameters(ICollection<string> assemblies = null)
{
var cparam = new CompilerParameters
{
GenerateInMemory = true,
GenerateExecutable = false
};
assemblies.NotNone(x => cparam.ReferencedAssemblies.AddRange(x.ToArray()));
UsingAssemblies.NotNone(x => cparam.ReferencedAssemblies.AddRange(x.ToArray()));
return cparam;
}
private static string FormatErrors(CompilerResults results) => results.Errors
.Cast<object>()
.Select((t, i) => results.Errors[i])
.Where(e => !e.IsWarning)
.Select(e => $"Line {e.Line}, Column {e.Column}, Error: {e.ErrorText}{Environment.NewLine}")
.Aggregate((a, e) => a + e);
private object CreatCompiledClass(string code, string className, ICollection<string> assemblies = null) =>
Compiled(code, assemblies)?.CreateInstance(className);
[UsedImplicitly]
public void AddFormul<T>(string name, string formul, params CodeDelegateParam[] delegateParams)
{
if (Delegates.All(x => x.Name != name))
Delegates.Add(new CodeDelegate(name, $"return {formul};", typeof(T), delegateParams));
}
[UsedImplicitly]
public void RevomeFormul(string name)
{
if (Delegates.Any(x => x.Name == name))
Delegates.Remove(Delegates.Find(x => x.Name == name));
}
[UsedImplicitly]
public Dictionary<string, Delegate> DelegatesList { get; } = new Dictionary<string, Delegate>();
[UsedImplicitly]
public void CompiledFormul( )
{
var cc = new CodeClass("Formul", "", "MathFormul", Parameters, null, null, null);
cc.Delegates.AddRange(Delegates);
var codeString = cc.ClassCodeString;
Value = CreatCompiledClass(codeString, "MathFormul.Formul", UsingAssemblies.ToArray());
UpedateDelegatesList();
}
private void UpedateDelegatesList()
{
DelegatesList.Clear();
if (Value.IsNull())
return;
foreach (var del in Delegates)
DelegatesList.Add(del.Name, DelegateTypeFactory.CreateDelegate(Value, del.Name));
}
[UsedImplicitly]
public Delegate Formul(string formul, params CodeDelegateParam[] delegateParams)
{
CodeClass cc = new CodeClass("Formul", "", "MathFormul", Parameters, null, null, null);
cc.Delegates.Add(new CodeDelegate("Result", $"return {formul};", typeof(decimal), delegateParams));
string codeString = cc.ClassCodeString;
var value = CreatCompiledClass(codeString, "MathFormul.Formul", UsingAssemblies.ToArray());
return DelegateTypeFactory.CreateDelegate(value, "Result");
}
[UsedImplicitly]
public object Value { get; private set; }
[UsedImplicitly]
public object InvokeMetod(string delegete, params object[] param) =>
DelegatesList[delegete].DynamicInvoke(param);
}
} |
|
Кликните здесь для просмотра всего текста
| C# | 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
| using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using HelpExtensionClass.Accessory.Delegates;
using HelpExtensionClass.Extension.CollectionExtension.CollectionNullEqualsExtension;
using HelpExtensionClass.Extension.ObjectExtension.ObjectNullEqualsExtension;
using JetBrains.Annotations;
using Microsoft.CSharp;
namespace HelpExtensionClass.Macro
{
/// <summary>
/// Компилятор C# кода
/// компилятор формул
/// </summary>
[UsedImplicitly]
public class Macro
{
/// <summary>
/// список параметров формул
/// </summary>
private Dictionary<string, object> ParamFormul { get; } = new Dictionary<string, object>();
/// <summary>
/// список подключаемых библеотек
/// </summary>
public List<string> UsingAssemblies { get; } = new List<string>();
/// <summary>
/// компилятор
/// </summary>
/// <param name="code"></param>
/// <param name="assemblies"></param>
/// <returns></returns>
private Assembly Compiled(string code, ICollection<string> assemblies = null)
{
var results = new CSharpCodeProvider().CompileAssemblyFromSource(CompilerParameters(assemblies), code);
if (results.Errors.HasErrors)
throw new ArgumentException("Ошибки при компиляции.");
return results.CompiledAssembly;
}
private CompilerParameters CompilerParameters(ICollection<string> assemblies = null)
{
var cparam = new CompilerParameters
{
GenerateInMemory = true,
GenerateExecutable = false
};
assemblies.NotNone(x => cparam.ReferencedAssemblies.AddRange(x.ToArray()));
UsingAssemblies.NotNone(x => cparam.ReferencedAssemblies.AddRange(x.ToArray()));
return cparam;
}
private object CreatCompiledClass(string code, string className, ICollection<string> assemblies = null) =>
Compiled(code, assemblies).CreateInstance(className);
/// <summary>
/// запускает метод неиспользуется
/// </summary>
/// <param name="objectclass"></param>
/// <param name="metod"></param>
/// <param name="param"></param>
/// <returns></returns>
[UsedImplicitly]
public object InvokeMetod(object objectclass, string metod, object[] param = null) =>
objectclass?.GetType().GetMethod(metod)?.Invoke(objectclass, param);
/// <summary>
/// форматирует параметры в строки кода
/// </summary>
/// <param name="paramFormul"></param>
/// <returns></returns>
private string ParamFormat(Dictionary<string, object> paramFormul = null) =>
ParamFormatewCode(paramFormul) + ParamFormatewCode(ParamFormul);
private static string ParamFormatewCode( Dictionary<string, object> paramFormul)
{
var paramFormuls = "";
if (paramFormul.NotNone())
foreach (var keyValue in paramFormul)
paramFormuls += $" public {keyValue.Value.GetType().FullName} {keyValue.Key} {{get;set;}}";
return paramFormuls;
}
/// <summary>
/// выполняет формулу
/// </summary>
/// <param name="formul"></param>
/// <param name="paramFormul"></param>
/// <returns></returns>
[UsedImplicitly]
public object MathFormul(string formul, Dictionary<string, object> paramFormul = null) => MathFormulDelegate(formul, paramFormul)();
/// <summary>
/// компелирует формулу в делегат
/// </summary>
/// <param name="formul"></param>
/// <param name="paramFormul"></param>
/// <returns></returns>
[UsedImplicitly]
public MathFormulDelegate MathFormulDelegate(string formul, Dictionary<string, object> paramFormul = null)
{
var cls = CreatCompiledClass($"namespace MathFormul {{ public class Formul {{ {ParamFormat(paramFormul)} public object Results(){{return {formul};}}}}}}", "MathFormul.Formul", new[] { "System.dll" });
//cls.GetType().GetProperties()
SetParm(paramFormul, cls);
if (cls.GetType().GetMethod("Results").NotNull())
return (MathFormulDelegate)Delegate.CreateDelegate(typeof(MathFormulDelegate), cls, "Results");
throw new ArgumentNullException();
}
private void SetParm(IDictionary<string, object> paramFormul, object cls)
{
foreach (var propertyInfo in cls.GetType().GetProperties())
{
if (paramFormul.NotNone() && paramFormul.ContainsKey(propertyInfo.Name))
propertyInfo.SetValue(cls, paramFormul[propertyInfo.Name]);
else if (ParamFormul.NotNone() && ParamFormul.ContainsKey(propertyInfo.Name))
propertyInfo.SetValue(cls, ParamFormul[propertyInfo.Name]);
}
}
}
} |
|
1
|