Initial commit
This commit is contained in:
@@ -0,0 +1,224 @@
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace RobotNet10.ScriptEngine.Shared;
|
||||
|
||||
public static partial class ScriptHelpers
|
||||
{
|
||||
public static string ToString(ParameterInfo parameter)
|
||||
{
|
||||
var modifier = "";
|
||||
if (parameter.IsDefined(typeof(ParamArrayAttribute), false))
|
||||
modifier = "params ";
|
||||
else if (parameter.IsIn && parameter.ParameterType.IsByRef && !parameter.IsOut)
|
||||
modifier = "in ";
|
||||
else if (parameter.IsOut)
|
||||
modifier = "out ";
|
||||
else if (parameter.ParameterType.IsByRef)
|
||||
modifier = "ref ";
|
||||
|
||||
var typeString = ScriptHelpers.ToString(
|
||||
parameter.ParameterType.IsByRef
|
||||
? parameter.ParameterType.GetElementType()!
|
||||
: parameter.ParameterType
|
||||
);
|
||||
|
||||
var defaultValue = "";
|
||||
if (parameter.HasDefaultValue)
|
||||
{
|
||||
if (parameter.DefaultValue != null)
|
||||
{
|
||||
if (parameter.ParameterType.IsEnum)
|
||||
{
|
||||
defaultValue = $" = {ScriptHelpers.ToString(parameter.ParameterType)}.{parameter.DefaultValue}";
|
||||
}
|
||||
else if (parameter.DefaultValue is string)
|
||||
{
|
||||
defaultValue = $" = \"{parameter.DefaultValue}\"";
|
||||
}
|
||||
else if (parameter.DefaultValue is bool b)
|
||||
{
|
||||
defaultValue = $" = {b.ToString().ToLower()}";
|
||||
}
|
||||
else
|
||||
{
|
||||
defaultValue = $" = {parameter.DefaultValue}";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
defaultValue = " = null";
|
||||
}
|
||||
}
|
||||
|
||||
return $"{modifier}{typeString} {parameter.Name}{defaultValue}";
|
||||
}
|
||||
|
||||
public static string ToString(Type type)
|
||||
{
|
||||
if (type == typeof(void)) return "void";
|
||||
|
||||
if (type.IsGenericType)
|
||||
{
|
||||
var genericTypeName = type.GetGenericTypeDefinition().FullName;
|
||||
if (genericTypeName == null)
|
||||
return type.Name;
|
||||
|
||||
var backtickIndex = genericTypeName.IndexOf('`');
|
||||
if (backtickIndex > 0)
|
||||
genericTypeName = genericTypeName[..backtickIndex];
|
||||
|
||||
var genericArgs = type.GetGenericArguments();
|
||||
var argsString = string.Join(", ", genericArgs.Select(ToString));
|
||||
return $"{genericTypeName}<{argsString}>";
|
||||
}
|
||||
|
||||
return type.FullName ?? type.Name;
|
||||
}
|
||||
|
||||
|
||||
public static Type? ResolveTypeFromString(string typeString)
|
||||
{
|
||||
typeString = typeString.Trim();
|
||||
|
||||
// Handle array types (e.g., System.Int32[], string[], List<int>[])
|
||||
if (typeString.EndsWith("[]"))
|
||||
{
|
||||
var elementTypeString = typeString[..^2].Trim();
|
||||
var elementType = ResolveTypeFromString(elementTypeString);
|
||||
return elementType?.MakeArrayType();
|
||||
}
|
||||
|
||||
// Trường hợp không phải generic
|
||||
if (!typeString.Contains('<'))
|
||||
{
|
||||
return FindType(typeString);
|
||||
}
|
||||
|
||||
// Tách phần generic
|
||||
var match = GenericTypeRegex.Match(typeString);
|
||||
if (!match.Success)
|
||||
return null;
|
||||
|
||||
var genericTypeName = match.Groups["raw"].Value;
|
||||
var genericArgsString = match.Groups["args"].Value;
|
||||
|
||||
// Phân tách các generic argument (xử lý nested generics)
|
||||
var genericArgs = SplitGenericArguments(genericArgsString);
|
||||
|
||||
var genericType = FindType(genericTypeName + "`" + genericArgs.Count);
|
||||
if (genericType == null)
|
||||
return null;
|
||||
|
||||
var resolvedArgs = genericArgs.Select(ResolveTypeFromString).ToArray();
|
||||
if (resolvedArgs.Any(t => t == null))
|
||||
return null;
|
||||
|
||||
return genericType.MakeGenericType(resolvedArgs!);
|
||||
}
|
||||
|
||||
public static bool ResolveValueFromString(string valueStr, Type type, out object? value)
|
||||
{
|
||||
// Check if type is in MissionParameterTypes
|
||||
if (!SupportedTypes.Values.Contains(type))
|
||||
{
|
||||
value = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Convert string to the corresponding type
|
||||
if (type == typeof(string))
|
||||
{
|
||||
value = valueStr;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (type.IsEnum)
|
||||
{
|
||||
value = Enum.Parse(type, valueStr, ignoreCase: true);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Handle nullable types
|
||||
var underlyingType = Nullable.GetUnderlyingType(type);
|
||||
if (underlyingType != null)
|
||||
{
|
||||
value = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
value = Convert.ChangeType(valueStr, type);
|
||||
if (value is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private static List<string> SplitGenericArguments(string input)
|
||||
{
|
||||
var args = new List<string>();
|
||||
var sb = new StringBuilder();
|
||||
int depth = 0;
|
||||
|
||||
foreach (char c in input)
|
||||
{
|
||||
if (c == ',' && depth == 0)
|
||||
{
|
||||
args.Add(sb.ToString().Trim());
|
||||
sb.Clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (c == '<') depth++;
|
||||
else if (c == '>') depth--;
|
||||
sb.Append(c);
|
||||
}
|
||||
}
|
||||
|
||||
if (sb.Length > 0)
|
||||
{
|
||||
args.Add(sb.ToString().Trim());
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
public static Type? FindType(string typeName)
|
||||
{
|
||||
if (SupportedTypes.TryGetValue(typeName, out var systemType)) return systemType;
|
||||
|
||||
return AppDomain.CurrentDomain
|
||||
.GetAssemblies()
|
||||
.Select(a => a.GetType(typeName, false))
|
||||
.FirstOrDefault(t => t != null);
|
||||
}
|
||||
|
||||
public static readonly IReadOnlyDictionary<string, Type> SupportedTypes = new Dictionary<string, Type>()
|
||||
{
|
||||
["bool"] = typeof(bool),
|
||||
["byte"] = typeof(byte),
|
||||
["sbyte"] = typeof(sbyte),
|
||||
["short"] = typeof(short),
|
||||
["ushort"] = typeof(ushort),
|
||||
["int"] = typeof(int),
|
||||
["uint"] = typeof(uint),
|
||||
["long"] = typeof(long),
|
||||
["ulong"] = typeof(ulong),
|
||||
["double"] = typeof(double),
|
||||
["float"] = typeof(float),
|
||||
["double"] = typeof(double),
|
||||
["char"] = typeof(char),
|
||||
["string"] = typeof(string),
|
||||
["object"] = typeof(object),
|
||||
};
|
||||
|
||||
private static readonly Regex GenericTypeRegex = CreateGenericTypeRegex();
|
||||
|
||||
[GeneratedRegex(@"^(?<raw>[^<]+)<(?<args>.+)>$")]
|
||||
private static partial Regex CreateGenericTypeRegex();
|
||||
}
|
||||
Reference in New Issue
Block a user