Elin Decompiled Documentation EA 23.315 Nightly
Loading...
Searching...
No Matches
DramaInvokeDetail.cs
Go to the documentation of this file.
1using System;
2using System.Collections.Generic;
3using System.IO;
4using System.Linq.Expressions;
5using System.Reflection;
6using UnityEngine;
7
8public class DramaInvokeDetail
9{
10 private Func<DramaManager, Dictionary<string, string>, string[], bool> _compiled;
11
12 private static readonly MethodInfo _stringIsNullOrEmpty = typeof(string).GetMethod("IsNullOrEmpty", new Type[1] { typeof(string) });
13
14 private static readonly ConstructorInfo _argumentException = typeof(ArgumentException).GetConstructor(new Type[1] { typeof(string) });
15
16 public MethodInfo Method { get; }
17
18 public string Contract { get; }
19
20 public bool NoDiscard => Contract.Contains("nodiscard");
21
22 public bool ParamPassthrough => Contract.Contains("passthrough");
23
24 public DramaInvokeDetail(MethodInfo method, string contract = null)
25 {
26 Method = method;
27 Contract = contract;
29 }
30
31 private void ValidateSignature()
32 {
33 if (!(Method == null))
34 {
35 if (Method.ContainsGenericParameters)
36 {
37 throw new NotSupportedException("#drama action cannot contain generic parameters");
38 }
39 if (!Method.IsStatic)
40 {
41 throw new NotSupportedException("#drama action must be static");
42 }
43 ParameterInfo[] parameters = Method.GetParameters();
44 if (parameters.Length < 2 || parameters[0].ParameterType != typeof(DramaManager) || parameters[1].ParameterType != typeof(Dictionary<string, string>) || Method.ReturnType != typeof(bool))
45 {
46 throw new ArgumentException("#drama action parameters must start with 'DramaManager dm, Dictionary<string, string>' and returns 'bool'");
47 }
48 }
49 }
50
51 private Func<DramaManager, Dictionary<string, string>, string[], bool> BuildDelegate()
52 {
53 ParameterInfo[] parameters = Method.GetParameters();
54 ParameterExpression parameterExpression = Expression.Parameter(typeof(DramaManager), "dm");
55 ParameterExpression parameterExpression2 = Expression.Parameter(typeof(Dictionary<string, string>), "line");
56 ParameterExpression parameterExpression3 = Expression.Parameter(typeof(string[]), "parameters");
57 List<Expression> list = new List<Expression> { parameterExpression, parameterExpression2 };
58 if (parameters.Length == 3 && parameters[2].ParameterType == typeof(string[]))
59 {
60 list.Add(parameterExpression3);
61 }
62 else if (parameters.Length > 2)
63 {
64 for (int i = 2; i < parameters.Length; i++)
65 {
66 ParameterInfo parameter = parameters[i];
67 int num = i - 2;
68 Expression expr = Expression.Condition(Expression.LessThan(Expression.Constant(num), Expression.ArrayLength(parameterExpression3)), Expression.ArrayIndex(parameterExpression3, Expression.Constant(num)), Expression.Constant(null, typeof(string)));
69 list.Add(CreateConvertExpression(expr, parameter));
70 }
71 }
72 return Expression.Lambda<Func<DramaManager, Dictionary<string, string>, string[], bool>>(Expression.Call(null, Method, list), new ParameterExpression[3] { parameterExpression, parameterExpression2, parameterExpression3 }).Compile();
73 }
74
75 private static Expression CreateConvertExpression(Expression expr, ParameterInfo parameter)
76 {
77 Type parameterType = parameter.ParameterType;
78 bool isOptional = parameter.IsOptional;
79 object defaultValue = parameter.DefaultValue;
80 string text = $"required action parameter #{parameter.Position - 2} '{parameter.Name}'";
81 if (parameterType == typeof(string))
82 {
83 MethodCallExpression test = Expression.Call(_stringIsNullOrEmpty, expr);
84 if (isOptional)
85 {
86 ConstantExpression ifTrue = Expression.Constant(defaultValue, typeof(string));
87 return Expression.Condition(test, ifTrue, expr);
88 }
89 string value = "#drama " + text + " cannot be empty";
90 UnaryExpression ifTrue2 = Expression.Throw(Expression.New(_argumentException, Expression.Constant(value)), typeof(string));
91 return Expression.Condition(test, ifTrue2, expr);
92 }
93 MethodInfo tryParseMethod = GetTryParseMethod(parameterType);
94 if (tryParseMethod == null)
95 {
96 throw new NotSupportedException("#drama type '" + parameterType.Name + "' does not have a public static TryParse method");
97 }
98 ParameterExpression parameterExpression = Expression.Variable(parameterType, "parsed");
99 Expression test2 = Expression.Call(tryParseMethod, expr, parameterExpression);
100 Expression expression;
101 if (isOptional)
102 {
103 expression = Expression.Constant(defaultValue, parameterType);
104 }
105 else
106 {
107 string value2 = "#drama can't parse " + text + " to type '" + parameterType.Name + "'";
108 expression = Expression.Throw(Expression.New(_argumentException, Expression.Constant(value2)), parameterType);
109 }
110 ConditionalExpression conditionalExpression = Expression.Condition(Expression.Call(_stringIsNullOrEmpty, expr), expression, Expression.Condition(test2, parameterExpression, expression));
111 return Expression.Block(new ParameterExpression[1] { parameterExpression }, conditionalExpression);
112 }
113
114 private static MethodInfo GetTryParseMethod(Type type)
115 {
116 if (type.IsEnum)
117 {
118 MethodInfo method = typeof(Enum).GetMethod("TryParse", BindingFlags.Static | BindingFlags.Public, null, new Type[2]
119 {
120 typeof(string),
121 type.MakeByRefType()
122 }, null);
123 if (method != null)
124 {
125 return method.MakeGenericMethod(type);
126 }
127 }
128 return type.GetMethod("TryParse", new Type[2]
129 {
130 typeof(string),
131 type.MakeByRefType()
132 });
133 }
134
135 public bool SafeInvoke(DramaManager dm, Dictionary<string, string> line, params string[] parameters)
136 {
137 if (Method == null)
138 {
139 return true;
140 }
141 try
142 {
143 if (_compiled == null)
144 {
146 }
147 return _compiled(dm, line, parameters);
148 }
149 catch (Exception ex)
150 {
151 ModUtil.LogModError("exception while invoking drama action '" + Method.TryToString() + "'\n" + ex.Message, new FileInfo(dm.path));
152 Debug.LogException(ex);
153 return false;
154 }
155 }
156}
Func< DramaManager, Dictionary< string, string >, string[], bool > BuildDelegate()
static readonly ConstructorInfo _argumentException
Func< DramaManager, Dictionary< string, string >, string[], bool > _compiled
static readonly MethodInfo _stringIsNullOrEmpty
bool SafeInvoke(DramaManager dm, Dictionary< string, string > line, params string[] parameters)
static MethodInfo GetTryParseMethod(Type type)
static Expression CreateConvertExpression(Expression expr, ParameterInfo parameter)
DramaInvokeDetail(MethodInfo method, string contract=null)