164 lines
6.8 KiB
C#
164 lines
6.8 KiB
C#
using System.Collections;
|
|
using System.Collections.Specialized;
|
|
using System.Net.Http.Formatting;
|
|
using System.Reflection;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Text.RegularExpressions;
|
|
|
|
namespace YLErp
|
|
{
|
|
[TestClass]
|
|
public class UnitTestBase
|
|
{
|
|
protected OptUserInfo GetOptUser([CallerMemberName] string m_name = "")
|
|
{
|
|
if (string.IsNullOrEmpty(m_name) || m_name == ".ctor")
|
|
{
|
|
m_name = GetType().Name;
|
|
}
|
|
|
|
return new OptUserInfo(0, m_name, OptUserFrom.UnitTest, userGroup: null);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 读取资源文件所有文本
|
|
/// </summary>
|
|
protected static string ReadResourceFile(string relativeFilePath)
|
|
{
|
|
var path = Path.Combine(AppContext.BaseDirectory, "Resources\\" + relativeFilePath);
|
|
return File.ReadAllText(path);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 读取资源文件所有行
|
|
/// </summary>
|
|
protected static string[] ReadResourceFileLines(string relativeFilePath)
|
|
{
|
|
var path = Path.Combine(AppContext.BaseDirectory, "Resources\\" + relativeFilePath);
|
|
return File.ReadAllLines(path);
|
|
}
|
|
|
|
protected static T DeserializeFormData<T>(string resourceFileRelativePath) where T : new()
|
|
{
|
|
var list = new List<KeyValuePair<string, string>>();
|
|
var lines = ReadResourceFileLines(resourceFileRelativePath);
|
|
|
|
foreach (var line in lines)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(line))
|
|
{
|
|
continue;
|
|
}
|
|
var index = line.IndexOf(':');
|
|
if (index < 0)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
list.Add(new KeyValuePair<string, string>(line.Substring(0, index).Trim(), line.Substring(index + 1).Trim()));
|
|
}
|
|
|
|
var fc = new FormDataCollection(list);
|
|
|
|
return MapForm<T>(fc.ReadAsNameValueCollection(), "");
|
|
}
|
|
|
|
protected class OtcOptionTradeFullFormData
|
|
{
|
|
public IEnumerable<OtcOptionTradeFull> trades { get; set; }
|
|
}
|
|
|
|
private static readonly Regex _regex = new(@"\[(?<value>.*?)\]", RegexOptions.Compiled | RegexOptions.Singleline);
|
|
|
|
private static T MapForm<T>(NameValueCollection nvc, string rootObjectName) where T : new()
|
|
{
|
|
var result = new T();
|
|
|
|
foreach (var kvp in nvc.AllKeys)
|
|
{
|
|
if (!kvp.StartsWith(rootObjectName))
|
|
{
|
|
throw new Exception("All keys should start with " + rootObjectName);
|
|
}
|
|
|
|
var match = _regex.Match(kvp.Remove(0, rootObjectName.Length));
|
|
|
|
if (match.Success)
|
|
{
|
|
// build path in a form of [Documents, 0, DocumentID]-like array
|
|
var path = new List<string>();
|
|
while (match.Success)
|
|
{
|
|
path.Add(match.Groups["value"].Value);
|
|
match = match.NextMatch();
|
|
}
|
|
// this is object we currently working on
|
|
object currentObject = result;
|
|
for (var i = 0; i < path.Count; i++)
|
|
{
|
|
var last = i == path.Count - 1;
|
|
var propName = path[i];
|
|
if (int.TryParse(propName, out var index))
|
|
{
|
|
// index access, like [0]
|
|
var list = currentObject as IList;
|
|
if (list == null)
|
|
{
|
|
throw new Exception("Invalid index access expression"); // more info here
|
|
}
|
|
// get the type of item in that list (i.e. Document)
|
|
var args = list.GetType().GetGenericArguments();
|
|
var listItemType = args[0];
|
|
if (last)
|
|
{
|
|
// may need more sophisticated conversion from string to target type
|
|
list[index] = Convert.ChangeType(nvc[kvp], Nullable.GetUnderlyingType(listItemType) ?? listItemType);
|
|
}
|
|
else
|
|
{
|
|
// if not initialized - initalize
|
|
var next = index < list.Count ? list[index] : null;
|
|
if (next == null)
|
|
{
|
|
// handle IList case in a special way here, since you cannot create instance of interface
|
|
next = Activator.CreateInstance(listItemType);
|
|
// fill with nulls if not enough items yet
|
|
while (index >= list.Count)
|
|
{
|
|
list.Add(null);
|
|
}
|
|
list[index] = next;
|
|
}
|
|
currentObject = next;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
var prop = currentObject.GetType().GetProperty(propName, BindingFlags.Instance | BindingFlags.Public);
|
|
if (last)
|
|
{
|
|
// may need more sophisticated conversion from string to target type
|
|
prop.SetValue(currentObject, Convert.ChangeType(nvc[kvp], Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType));
|
|
}
|
|
else
|
|
{
|
|
// if not initialized - initalize
|
|
var next = prop.GetValue(currentObject);
|
|
if (next == null)
|
|
{
|
|
// TODO: handle IList case in a special way here, since you cannot create instance of interface
|
|
next = Activator.CreateInstance(prop.PropertyType);
|
|
prop.SetValue(currentObject, next);
|
|
}
|
|
currentObject = next;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
}
|
|
}
|