* EnumEx: DisplayText特性改为原生的Description特性
This commit is contained in:
parent
00897c5cc5
commit
0d989a75ea
@ -249,9 +249,9 @@ namespace Sunny.UI
|
|||||||
{
|
{
|
||||||
Angle angle = Angles[pieIndex][azIndex];
|
Angle angle = Angles[pieIndex][azIndex];
|
||||||
PointF pf = angle.Center;
|
PointF pf = angle.Center;
|
||||||
if (Drawing.CalcDistance(e.Location, pf) > angle.Outer) continue;
|
if (e.Location.CalcDistance(pf) > angle.Outer) continue;
|
||||||
if (Drawing.CalcDistance(e.Location, pf) < angle.Inner) continue;
|
if (e.Location.CalcDistance(pf) < angle.Inner) continue;
|
||||||
double az = Drawing.CalcAngle(e.Location, pf);
|
double az = e.Location.CalcAngle(pf);
|
||||||
if (az >= angle.Start && az <= angle.Start + angle.Sweep)
|
if (az >= angle.Start && az <= angle.Start + angle.Sweep)
|
||||||
{
|
{
|
||||||
SetPieAndAzIndex(pieIndex, azIndex);
|
SetPieAndAzIndex(pieIndex, azIndex);
|
||||||
|
@ -274,9 +274,9 @@ namespace Sunny.UI
|
|||||||
if (!e.Location.InRect(rect)) continue;
|
if (!e.Location.InRect(rect)) continue;
|
||||||
|
|
||||||
PointF pf = new PointF(rect.Left + rect.Width / 2.0f, rect.Top + rect.Height / 2.0f);
|
PointF pf = new PointF(rect.Left + rect.Width / 2.0f, rect.Top + rect.Height / 2.0f);
|
||||||
if (Drawing.CalcDistance(e.Location, pf) * 2 > rect.Width) continue;
|
if (e.Location.CalcDistance(pf) * 2 > rect.Width) continue;
|
||||||
|
|
||||||
double az = Drawing.CalcAngle(e.Location, pf);
|
double az = e.Location.CalcAngle(pf);
|
||||||
for (int azIndex = 0; azIndex < Option.Series[pieIndex].Data.Count; azIndex++)
|
for (int azIndex = 0; azIndex < Option.Series[pieIndex].Data.Count; azIndex++)
|
||||||
{
|
{
|
||||||
Angle angle = Angles[pieIndex][azIndex];
|
Angle angle = Angles[pieIndex][azIndex];
|
||||||
|
743
SunnyUI/Common/UBaseConfig.cs
Normal file
743
SunnyUI/Common/UBaseConfig.cs
Normal file
@ -0,0 +1,743 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* SunnyUI 开源控件库、工具类库、扩展类库、多页面开发框架。
|
||||||
|
* CopyRight (C) 2012-2023 ShenYongHua(沈永华).
|
||||||
|
* QQ群:56829229 QQ:17612584 EMail:SunnyUI@QQ.Com
|
||||||
|
*
|
||||||
|
* Blog: https://www.cnblogs.com/yhuse
|
||||||
|
* Gitee: https://gitee.com/yhuse/SunnyUI
|
||||||
|
* GitHub: https://github.com/yhuse/SunnyUI
|
||||||
|
*
|
||||||
|
* SunnyUI.Common.dll can be used for free under the MIT license.
|
||||||
|
* If you use this code, please keep this note.
|
||||||
|
* 如果您使用此代码,请保留此说明。
|
||||||
|
******************************************************************************
|
||||||
|
* 文件名称: UBaseConfig.cs
|
||||||
|
* 文件说明: 配置文件基类
|
||||||
|
* 当前版本: V3.1
|
||||||
|
* 创建日期: 2020-01-01
|
||||||
|
*
|
||||||
|
* 2020-01-01: V2.2.0 增加文件说明
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
|
namespace Sunny.UI
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 配置文件基类
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TConfig">类型</typeparam>
|
||||||
|
public abstract class BaseConfig<TConfig> where TConfig : BaseConfig<TConfig>, new()
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 实体对象
|
||||||
|
/// </summary>
|
||||||
|
protected static TConfig current;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 配置文件描述
|
||||||
|
/// </summary>
|
||||||
|
public static string Description
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var fileanddesc = ConfigHelper.GetConfigFile<TConfig>();
|
||||||
|
return fileanddesc.Item2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 配置文件名
|
||||||
|
/// </summary>
|
||||||
|
public static string ConfigFile
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
var fileanddesc = ConfigHelper.GetConfigFile<TConfig>();
|
||||||
|
return fileanddesc.Item1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当前可执行文件路径,末尾包括\
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>结果</returns>
|
||||||
|
private static string CurrentDir()
|
||||||
|
{
|
||||||
|
return Environment.CurrentDirectory.DealPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当前实例。通过置空可以使其重新加载。
|
||||||
|
/// </summary>
|
||||||
|
public static TConfig Current
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (current != null)
|
||||||
|
{
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 现在没有对象,尝试加载,若返回null则实例化一个新的
|
||||||
|
current = CreateNew();
|
||||||
|
if (!current.Load(CurrentDir() + ConfigFile))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 根据配置,有可能不保存,直接返回默认
|
||||||
|
current.Save();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex.Message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
|
set => current = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TConfig CreateNew()
|
||||||
|
{
|
||||||
|
TConfig config = new TConfig();
|
||||||
|
config.SetDefault();
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>保存到配置文件中去</summary>
|
||||||
|
public void Save()
|
||||||
|
{
|
||||||
|
Save(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 加载指定配置文件
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>结果</returns>
|
||||||
|
public bool Load()
|
||||||
|
{
|
||||||
|
return Load(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 加密
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="str">字符串</param>
|
||||||
|
/// <returns>加密后字符串</returns>
|
||||||
|
public string Encrypt(string str)
|
||||||
|
{
|
||||||
|
Random random = new Random();
|
||||||
|
var value = random.Next(100000, 999999);
|
||||||
|
string tmp = str + value.ToString();
|
||||||
|
return tmp.DesEncrypt();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 解密
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="str">字符串</param>
|
||||||
|
/// <returns>解密后字符串</returns>
|
||||||
|
public string Decrypt(string str)
|
||||||
|
{
|
||||||
|
string result = str.DesDecrypt();
|
||||||
|
return result.Left(result.Length - 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>加载指定配置文件</summary>
|
||||||
|
/// <param name="filename">文件名</param>
|
||||||
|
/// <returns>结果</returns>
|
||||||
|
public abstract bool Load(string filename);
|
||||||
|
|
||||||
|
/// <summary>保存到配置文件中去</summary>
|
||||||
|
/// <param name="filename">文件名</param>
|
||||||
|
public abstract void Save(string filename);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设置默认值
|
||||||
|
/// </summary>
|
||||||
|
public virtual void SetDefault()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 忽略此属性的配置存储
|
||||||
|
/// </summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Property)]
|
||||||
|
public class MapperIgnoreAttribute : Attribute
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 忽略此属性的配置存储
|
||||||
|
/// </summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Property)]
|
||||||
|
public class IgnoreAttribute : Attribute
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 配置文件帮助类
|
||||||
|
/// </summary>
|
||||||
|
public static class ConfigHelper
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 类型是否能够转为指定基类
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">类型</param>
|
||||||
|
/// <param name="baseType">基类</param>
|
||||||
|
/// <returns>是否能够转为指定基类</returns>
|
||||||
|
public static bool As(this Type type, Type baseType)
|
||||||
|
{
|
||||||
|
if (type == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果基类是泛型定义
|
||||||
|
if (baseType.IsGenericTypeDefinition && type.IsGenericType && !type.IsGenericTypeDefinition)
|
||||||
|
{
|
||||||
|
type = type.GetGenericTypeDefinition();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == baseType)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (baseType.IsAssignableFrom(type))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var rs = false;
|
||||||
|
|
||||||
|
// 接口
|
||||||
|
if (baseType.IsInterface)
|
||||||
|
{
|
||||||
|
if (type.GetInterface(baseType.FullName) != null)
|
||||||
|
{
|
||||||
|
rs = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
foreach (var e in type.GetInterfaces())
|
||||||
|
{
|
||||||
|
if (e.IsGenericType && baseType.IsGenericTypeDefinition ? e.GetGenericTypeDefinition() == baseType : e == baseType)
|
||||||
|
{
|
||||||
|
rs = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 判断是否子类时,支持只反射加载的程序集
|
||||||
|
if (!rs && type.Assembly.ReflectionOnly)
|
||||||
|
{
|
||||||
|
// 反射加载时,需要特殊处理接口
|
||||||
|
while (!rs && type != typeof(object))
|
||||||
|
{
|
||||||
|
if (type == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type.FullName == baseType.FullName && type.AssemblyQualifiedName == baseType.AssemblyQualifiedName)
|
||||||
|
{
|
||||||
|
rs = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
type = type.BaseType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>是否泛型字典</summary>
|
||||||
|
/// <param name="type">类型</param>
|
||||||
|
/// <returns>是否泛型字典</returns>
|
||||||
|
public static bool IsDictionary(this Type type) => type != null && type.IsGenericType && type.As(typeof(IDictionary<,>));
|
||||||
|
|
||||||
|
/// <summary>是否泛型列表</summary>
|
||||||
|
/// <param name="type">类型</param>
|
||||||
|
/// <returns>是否泛型列表</returns>
|
||||||
|
public static bool IsList(this Type type)
|
||||||
|
{
|
||||||
|
return type != null && type.IsGenericType && type.As(typeof(IList<>));
|
||||||
|
//return Array.IndexOf(type.GetInterfaces(), typeof(IEnumerable)) > -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>获取成员绑定的显示名,优先DisplayName,然后Description</summary>
|
||||||
|
/// <param name="member">member</param>
|
||||||
|
/// <returns>显示名</returns>
|
||||||
|
public static string DisplayName(this PropertyInfo member)
|
||||||
|
{
|
||||||
|
var att = member.GetCustomAttribute<DisplayNameAttribute>();
|
||||||
|
if (att != null && !att.DisplayName.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
return att.DisplayName;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>获取成员绑定的显示名,优先DisplayName,然后Description</summary>
|
||||||
|
/// <param name="member">member</param>
|
||||||
|
/// <returns>显示名</returns>
|
||||||
|
public static string Description(this PropertyInfo member)
|
||||||
|
{
|
||||||
|
var att2 = member.GetCustomAttribute<DescriptionAttribute>();
|
||||||
|
if (att2 != null && !att2.Description.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
return att2.Description;
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取需要的属性,删除忽略的属性
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">类型</param>
|
||||||
|
/// <returns>属性列表</returns>
|
||||||
|
public static List<PropertyInfo> GetNeedProperties(this Type type)
|
||||||
|
{
|
||||||
|
var list = type.GetProperties();
|
||||||
|
List<PropertyInfo> result = new List<PropertyInfo>();
|
||||||
|
foreach (var info in list)
|
||||||
|
{
|
||||||
|
if (info.GetCustomAttribute<XmlIgnoreAttribute>() != null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.GetCustomAttribute<ConfigIgnoreAttribute>() != null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.GetCustomAttribute<MapperIgnoreAttribute>() != null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.GetCustomAttribute<IgnoreAttribute>() != null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.Add(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取配置文件路径
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TConfig">类型</typeparam>
|
||||||
|
/// <returns>文件名</returns>
|
||||||
|
public static Tuple<string, string> GetConfigFile<TConfig>()
|
||||||
|
{
|
||||||
|
string filename;
|
||||||
|
string description = "配置文件";
|
||||||
|
var att = typeof(TConfig).GetCustomAttribute<ConfigFileAttribute>();
|
||||||
|
if (att == null || att.FileName.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
filename = $"{typeof(TConfig).Name}.cfg";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
filename = att.FileName;
|
||||||
|
|
||||||
|
if (!att.Description.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
description = att.Description;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Tuple<string, string>(filename, description);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 初始化属性
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="config">配置类</param>
|
||||||
|
/// <typeparam name="TConfig">类型</typeparam>
|
||||||
|
/// <returns>节点</returns>
|
||||||
|
/// <exception cref="ApplicationException">ApplicationException</exception>
|
||||||
|
public static ConcurrentDictionary<string, Ident> InitIdents<TConfig>(TConfig config)
|
||||||
|
{
|
||||||
|
ConcurrentDictionary<string, Ident> idents = new ConcurrentDictionary<string, Ident>();
|
||||||
|
var list = config.GetType().GetNeedProperties();
|
||||||
|
foreach (PropertyInfo info in list)
|
||||||
|
{
|
||||||
|
Ident ident = new Ident
|
||||||
|
{
|
||||||
|
Key = info.Name,
|
||||||
|
Show = true,
|
||||||
|
Description = info.Description(),
|
||||||
|
IsList = info.PropertyType.IsList()
|
||||||
|
};
|
||||||
|
|
||||||
|
var section = info.GetCustomAttribute<ConfigSectionAttribute>();
|
||||||
|
ident.Section = section != null ? section.Section : "";
|
||||||
|
|
||||||
|
var propertyatt = info.GetCustomAttribute<ConfigPropertyAttribute>();
|
||||||
|
ident.Caption = propertyatt != null ? propertyatt.Caption : "";
|
||||||
|
ident.Unit = propertyatt != null ? propertyatt.Unit : "";
|
||||||
|
ident.Description = propertyatt != null ? propertyatt.Description : "";
|
||||||
|
|
||||||
|
var indexatt = info.GetCustomAttribute<ConfigIndexAttribute>();
|
||||||
|
ident.Index = indexatt?.Index ?? short.MaxValue + idents.Count;
|
||||||
|
ident.Show = indexatt == null || indexatt.Show;
|
||||||
|
|
||||||
|
if (ident.Description.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
ident.Description = info.DisplayName() ?? info.Description();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ident.Description.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
ident.Description = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!idents.ContainsKey(ident.Key))
|
||||||
|
{
|
||||||
|
idents.TryAdd(ident.Key, ident);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return idents;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 类型默认值
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="targetType">类型</param>
|
||||||
|
/// <returns>默认值</returns>
|
||||||
|
public static object DefaultValue(Type targetType)
|
||||||
|
{
|
||||||
|
return targetType.IsValueType ? Activator.CreateInstance(targetType) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读取对象数值
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="config">配置文件</param>
|
||||||
|
/// <param name="idents">节点</param>
|
||||||
|
/// <typeparam name="TConfig">类型</typeparam>
|
||||||
|
/// <exception cref="ApplicationException">ApplicationException</exception>
|
||||||
|
public static void LoadConfigValue<TConfig>(TConfig config, ConcurrentDictionary<string, Ident> idents)
|
||||||
|
{
|
||||||
|
var list = config.GetType().GetNeedProperties();
|
||||||
|
foreach (PropertyInfo info in list)
|
||||||
|
{
|
||||||
|
object defaultobj = info.GetValue(config, null);
|
||||||
|
Type type = info.PropertyType;
|
||||||
|
|
||||||
|
if (type == typeof(string))
|
||||||
|
{
|
||||||
|
object value = idents[info.Name].Value;
|
||||||
|
info.SetValue(config, Convert.ChangeType(value == null ? defaultobj : value, type), null);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ConvertEx.CanConvent(type))
|
||||||
|
{
|
||||||
|
object value = ConvertEx.StringToObject(idents[info.Name].Value, type, defaultobj);
|
||||||
|
info.SetValue(config, Convert.ChangeType(value, type), null);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type.IsList())
|
||||||
|
{
|
||||||
|
Type[] genericTypes = type.GetGenericArguments();
|
||||||
|
if (genericTypes.Length != 1)
|
||||||
|
{
|
||||||
|
throw new ApplicationException("转换出错: " + type.FullName);
|
||||||
|
}
|
||||||
|
|
||||||
|
Type childtype = genericTypes[0];
|
||||||
|
Type typeDataList = typeof(List<>).MakeGenericType(childtype);
|
||||||
|
MethodInfo methodInfo = typeDataList.GetMethod("Add", BindingFlags.Public | BindingFlags.Instance);
|
||||||
|
if (methodInfo == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
object listvalue = typeDataList.InvokeMember(null, BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.CreateInstance, null, null, new object[] { });
|
||||||
|
|
||||||
|
foreach (string strvalue in idents[info.Name].Values)
|
||||||
|
{
|
||||||
|
if (childtype == typeof(string))
|
||||||
|
{
|
||||||
|
object value = strvalue;
|
||||||
|
methodInfo.Invoke(listvalue, new[] { value });
|
||||||
|
}
|
||||||
|
else if (ConvertEx.CanConvent(childtype))
|
||||||
|
{
|
||||||
|
object value = ConvertEx.StringToObject(strvalue, childtype, DefaultValue(childtype));
|
||||||
|
methodInfo.Invoke(listvalue, new[] { value });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
info.SetValue(config, listvalue, null);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new ApplicationException("不支持此类型: " + type.FullName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设置对象数值
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="config">配置文件</param>
|
||||||
|
/// <param name="idents">节点</param>
|
||||||
|
/// <typeparam name="TConfig">类型</typeparam>
|
||||||
|
/// <exception cref="ApplicationException">ApplicationException</exception>
|
||||||
|
public static void SaveConfigValue<TConfig>(TConfig config, ConcurrentDictionary<string, Ident> idents)
|
||||||
|
{
|
||||||
|
var list = config.GetType().GetNeedProperties();
|
||||||
|
foreach (PropertyInfo info in list)
|
||||||
|
{
|
||||||
|
object obj = info.GetValue(config, null);
|
||||||
|
Type type = info.PropertyType;
|
||||||
|
|
||||||
|
if (ConvertEx.CanConvent(type))
|
||||||
|
{
|
||||||
|
string value = ConvertEx.ObjectToString(obj, type);
|
||||||
|
idents[info.Name].Value = value;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type.IsList())
|
||||||
|
{
|
||||||
|
Type[] genericTypes = type.GetGenericArguments();
|
||||||
|
if (genericTypes.Length != 1)
|
||||||
|
{
|
||||||
|
throw new ApplicationException("转换出错: " + type.FullName);
|
||||||
|
}
|
||||||
|
|
||||||
|
Type childtype = genericTypes[0];
|
||||||
|
IEnumerable en = obj as IEnumerable;
|
||||||
|
if (en == null)
|
||||||
|
{
|
||||||
|
throw new ApplicationException("转换出错: " + type.FullName);
|
||||||
|
}
|
||||||
|
|
||||||
|
idents[info.Name].Values.Clear();
|
||||||
|
foreach (object child in en)
|
||||||
|
{
|
||||||
|
if (ConvertEx.CanConvent(childtype))
|
||||||
|
{
|
||||||
|
idents[info.Name].Values.Add(ConvertEx.ObjectToString(child, childtype));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new ApplicationException("不支持此类型: " + type.FullName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new ApplicationException("不支持此类型: " + type.FullName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>配置文件特性</summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Class)]
|
||||||
|
public class ConfigFileAttribute : Attribute
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 配置文件名
|
||||||
|
/// </summary>
|
||||||
|
public string FileName { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 描述
|
||||||
|
/// </summary>
|
||||||
|
public string Description { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 配置文件
|
||||||
|
/// </summary>
|
||||||
|
public ConfigFileAttribute() : this(string.Empty, string.Empty)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>配置文件</summary>
|
||||||
|
/// <param name="fileName">文件名</param>
|
||||||
|
/// <param name="description">描述</param>
|
||||||
|
public ConfigFileAttribute(string fileName, string description = "")
|
||||||
|
{
|
||||||
|
FileName = fileName;
|
||||||
|
Description = description;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 数据节点
|
||||||
|
/// </summary>
|
||||||
|
public class Ident
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 节
|
||||||
|
/// </summary>
|
||||||
|
public string Section { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 键
|
||||||
|
/// </summary>
|
||||||
|
public string Key { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 值
|
||||||
|
/// </summary>
|
||||||
|
public string Value { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 描述
|
||||||
|
/// </summary>
|
||||||
|
public string Description { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 名称
|
||||||
|
/// </summary>
|
||||||
|
public string Caption { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 单位
|
||||||
|
/// </summary>
|
||||||
|
public string Unit { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 序号
|
||||||
|
/// </summary>
|
||||||
|
public int Index { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否显示
|
||||||
|
/// </summary>
|
||||||
|
public bool Show { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ToString()
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>String</returns>
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return Index + " [" + Section + "] " + Key + " = ?";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否是列表类型
|
||||||
|
/// </summary>
|
||||||
|
public bool IsList { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 列表值
|
||||||
|
/// </summary>
|
||||||
|
public List<string> Values = new List<string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 配置属性节点特性
|
||||||
|
/// </summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Property)]
|
||||||
|
public class ConfigSectionAttribute : Attribute
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 节
|
||||||
|
/// </summary>
|
||||||
|
public string Section { get; }
|
||||||
|
|
||||||
|
/// <summary>属性节点特性</summary>
|
||||||
|
/// <param name="section">节</param>
|
||||||
|
public ConfigSectionAttribute(string section)
|
||||||
|
{
|
||||||
|
Section = section;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 配置属性描述特性
|
||||||
|
/// </summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Property)]
|
||||||
|
public class ConfigPropertyAttribute : Attribute
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 标题
|
||||||
|
/// </summary>
|
||||||
|
public string Caption { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 单位
|
||||||
|
/// </summary>
|
||||||
|
public string Unit { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 描述
|
||||||
|
/// </summary>
|
||||||
|
public string Description { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 配置文件属性
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="caption">标题</param>
|
||||||
|
/// <param name="unit">单位</param>
|
||||||
|
/// <param name="description">描述</param>
|
||||||
|
public ConfigPropertyAttribute(string caption, string description = "", string unit = "")
|
||||||
|
{
|
||||||
|
Caption = caption;
|
||||||
|
Unit = unit;
|
||||||
|
Description = description;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 忽略此属性的配置存储
|
||||||
|
/// </summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Property)]
|
||||||
|
public class ConfigIgnoreAttribute : Attribute
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 配置序号描述特性
|
||||||
|
/// </summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Property)]
|
||||||
|
public class ConfigIndexAttribute : Attribute
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 序号
|
||||||
|
/// </summary>
|
||||||
|
public int Index { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否显示
|
||||||
|
/// </summary>
|
||||||
|
public bool Show { get; }
|
||||||
|
|
||||||
|
/// <summary>配置序号特性</summary>
|
||||||
|
/// <param name="index">序号</param>
|
||||||
|
/// <param name="show">是否显示</param>
|
||||||
|
public ConfigIndexAttribute(int index, bool show = true)
|
||||||
|
{
|
||||||
|
Index = index;
|
||||||
|
Show = show;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
371
SunnyUI/Common/UConvertEx.cs
Normal file
371
SunnyUI/Common/UConvertEx.cs
Normal file
@ -0,0 +1,371 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* SunnyUI 开源控件库、工具类库、扩展类库、多页面开发框架。
|
||||||
|
* CopyRight (C) 2012-2023 ShenYongHua(沈永华).
|
||||||
|
* QQ群:56829229 QQ:17612584 EMail:SunnyUI@QQ.Com
|
||||||
|
*
|
||||||
|
* Blog: https://www.cnblogs.com/yhuse
|
||||||
|
* Gitee: https://gitee.com/yhuse/SunnyUI
|
||||||
|
* GitHub: https://github.com/yhuse/SunnyUI
|
||||||
|
*
|
||||||
|
* SunnyUI.Common.dll can be used for free under the MIT license.
|
||||||
|
* If you use this code, please keep this note.
|
||||||
|
* 如果您使用此代码,请保留此说明。
|
||||||
|
******************************************************************************
|
||||||
|
* 文件名称: UConvertEx.cs
|
||||||
|
* 文件说明: 对象转换扩展类
|
||||||
|
* 当前版本: V3.1
|
||||||
|
* 创建日期: 2020-01-01
|
||||||
|
*
|
||||||
|
* 2020-11-20: V3.0.0 增加文件说明
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Drawing;
|
||||||
|
|
||||||
|
namespace Sunny.UI
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 对象转换扩展类
|
||||||
|
/// </summary>
|
||||||
|
public static class ConvertEx
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 可以对象和字符串互相转换的类型
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type">类型</param>
|
||||||
|
/// <returns>结果</returns>
|
||||||
|
public static bool CanConvent(Type type)
|
||||||
|
{
|
||||||
|
bool result = false;
|
||||||
|
TypeCode typeCode = Type.GetTypeCode(type);
|
||||||
|
switch (typeCode)
|
||||||
|
{
|
||||||
|
case TypeCode.String:
|
||||||
|
case TypeCode.Char:
|
||||||
|
case TypeCode.SByte:
|
||||||
|
case TypeCode.Byte:
|
||||||
|
case TypeCode.Int16:
|
||||||
|
case TypeCode.UInt16:
|
||||||
|
case TypeCode.Int32:
|
||||||
|
case TypeCode.UInt32:
|
||||||
|
case TypeCode.Int64:
|
||||||
|
case TypeCode.UInt64:
|
||||||
|
case TypeCode.Single:
|
||||||
|
case TypeCode.Double:
|
||||||
|
case TypeCode.Decimal:
|
||||||
|
case TypeCode.Boolean:
|
||||||
|
case TypeCode.DateTime:
|
||||||
|
result = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TypeCode.Object:
|
||||||
|
if (type == typeof(Point) ||
|
||||||
|
type == typeof(PointF) ||
|
||||||
|
type == typeof(Color) ||
|
||||||
|
type == typeof(Size) ||
|
||||||
|
type == typeof(SizeF))
|
||||||
|
{
|
||||||
|
result = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 字符串转对象
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="str">字符串</param>
|
||||||
|
/// <param name="type">类型</param>
|
||||||
|
/// <param name="defaultobj">默认对象</param>
|
||||||
|
/// <returns>对象</returns>
|
||||||
|
public static object StringToObject(string str, Type type, object defaultobj)
|
||||||
|
{
|
||||||
|
object obj = defaultobj;
|
||||||
|
|
||||||
|
if (type == typeof(string))
|
||||||
|
{
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (str.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
return defaultobj;
|
||||||
|
}
|
||||||
|
|
||||||
|
TypeCode typeCode = Type.GetTypeCode(type);
|
||||||
|
switch (typeCode)
|
||||||
|
{
|
||||||
|
case TypeCode.Char:
|
||||||
|
obj = str.ToChar((char)defaultobj);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TypeCode.SByte:
|
||||||
|
obj = str.ToSByte((sbyte)defaultobj);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TypeCode.Byte:
|
||||||
|
obj = str.ToByte((byte)defaultobj);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TypeCode.Int16:
|
||||||
|
obj = str.ToShort((short)defaultobj);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TypeCode.UInt16:
|
||||||
|
obj = str.ToUShort((ushort)defaultobj);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TypeCode.Int32:
|
||||||
|
obj = str.ToInt((int)defaultobj);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TypeCode.UInt32:
|
||||||
|
obj = str.ToUInt((uint)defaultobj);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TypeCode.Int64:
|
||||||
|
obj = str.ToLong((long)defaultobj);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TypeCode.UInt64:
|
||||||
|
obj = str.ToULong((ulong)defaultobj);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TypeCode.Single:
|
||||||
|
obj = str.ToFloat((float)defaultobj);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TypeCode.Double:
|
||||||
|
obj = str.ToDouble((double)defaultobj);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TypeCode.Decimal:
|
||||||
|
obj = str.ToDecimal((decimal)defaultobj);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TypeCode.Boolean:
|
||||||
|
if (str.ToUpper().Equals(bool.TrueString.ToUpper()))
|
||||||
|
{
|
||||||
|
obj = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (str.ToUpper().Equals(bool.FalseString.ToUpper()))
|
||||||
|
{
|
||||||
|
obj = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TypeCode.DateTime:
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DateTime dt = str.ToDateTime(DateTimeEx.DateTimeFormat);
|
||||||
|
obj = dt;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TypeCode.Object:
|
||||||
|
obj = StringToObjectEx(str, type, defaultobj);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new ApplicationException("不支持此类型: " + type.FullName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == typeof(DateTime))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 字符串转对象扩展
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="str">字符串</param>
|
||||||
|
/// <param name="type">类型</param>
|
||||||
|
/// <param name="defaultobj">默认对象</param>
|
||||||
|
/// <returns>对象</returns>
|
||||||
|
private static object StringToObjectEx(string str, Type type, object defaultobj)
|
||||||
|
{
|
||||||
|
object obj = defaultobj;
|
||||||
|
|
||||||
|
if (type == typeof(Point))
|
||||||
|
{
|
||||||
|
string[] strs = str.ToUpper().Replace("X:", "").Replace("Y:", "").Trim().Split(";");
|
||||||
|
|
||||||
|
if (strs.Length == 2)
|
||||||
|
{
|
||||||
|
if (int.TryParse(strs[0], out var x) && int.TryParse(strs[1], out var y))
|
||||||
|
{
|
||||||
|
obj = new Point(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type == typeof(PointF))
|
||||||
|
{
|
||||||
|
string[] strs = str.ToUpper().Replace("X:", "").Replace("Y:", "").Trim().Split(";");
|
||||||
|
|
||||||
|
if (strs.Length == 2)
|
||||||
|
{
|
||||||
|
if (float.TryParse(strs[0], out var x) && float.TryParse(strs[1], out var y))
|
||||||
|
{
|
||||||
|
obj = new PointF(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type == typeof(Color))
|
||||||
|
{
|
||||||
|
string[] strs = str.ToUpper().Replace("A:", "").Replace("R:", "").Replace("G:", "").Replace("B:", "").Trim().Split(";");
|
||||||
|
|
||||||
|
if (strs.Length == 4)
|
||||||
|
{
|
||||||
|
if (int.TryParse(strs[0], out var a) && int.TryParse(strs[1], out var r) && int.TryParse(strs[2], out var g) && int.TryParse(strs[3], out var b))
|
||||||
|
{
|
||||||
|
if (a.InRange(0, 255) && r.InRange(0, 255) && g.InRange(0, 255) && b.InRange(0, 255))
|
||||||
|
{
|
||||||
|
obj = Color.FromArgb(a, r, g, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type == typeof(Size))
|
||||||
|
{
|
||||||
|
string[] strs = str.ToUpper().Replace("W:", "").Replace("H:", "").Trim().Split(";");
|
||||||
|
|
||||||
|
if (strs.Length == 2)
|
||||||
|
{
|
||||||
|
if (int.TryParse(strs[0], out var x) && int.TryParse(strs[1], out var y))
|
||||||
|
{
|
||||||
|
obj = new Size(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type == typeof(SizeF))
|
||||||
|
{
|
||||||
|
string[] strs = str.ToUpper().Replace("W:", "").Replace("H:", "").Trim().Split(";");
|
||||||
|
|
||||||
|
if (strs.Length == 2)
|
||||||
|
{
|
||||||
|
if (float.TryParse(strs[0], out var x) && float.TryParse(strs[1], out var y))
|
||||||
|
{
|
||||||
|
obj = new SizeF(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new ApplicationException("不支持此类型: " + type.FullName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 对象转字符串
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="obj">对象</param>
|
||||||
|
/// <param name="type">类型</param>
|
||||||
|
/// <returns>字符串</returns>
|
||||||
|
public static string ObjectToString(object obj, Type type)
|
||||||
|
{
|
||||||
|
string value;
|
||||||
|
|
||||||
|
TypeCode typeCode = Type.GetTypeCode(type);
|
||||||
|
switch (typeCode)
|
||||||
|
{
|
||||||
|
case TypeCode.String:
|
||||||
|
if (obj == null)
|
||||||
|
{
|
||||||
|
obj = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
value = obj.ToString();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TypeCode.Char:
|
||||||
|
case TypeCode.SByte:
|
||||||
|
case TypeCode.Byte:
|
||||||
|
case TypeCode.Int16:
|
||||||
|
case TypeCode.UInt16:
|
||||||
|
case TypeCode.Int32:
|
||||||
|
case TypeCode.UInt32:
|
||||||
|
case TypeCode.Int64:
|
||||||
|
case TypeCode.UInt64:
|
||||||
|
case TypeCode.Single:
|
||||||
|
case TypeCode.Double:
|
||||||
|
case TypeCode.Decimal:
|
||||||
|
value = obj.ToString();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TypeCode.Boolean:
|
||||||
|
value = (bool)obj ? bool.TrueString : bool.FalseString;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TypeCode.DateTime:
|
||||||
|
value = ((DateTime)obj).ToString(DateTimeEx.DateTimeFormat);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TypeCode.Object:
|
||||||
|
value = ObjectToStringEx(obj, type);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new ApplicationException("不支持此类型: " + type.FullName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 对象转字符串扩展
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="obj">对象</param>
|
||||||
|
/// <param name="type">类型</param>
|
||||||
|
/// <returns>字符串</returns>
|
||||||
|
private static string ObjectToStringEx(object obj, Type type)
|
||||||
|
{
|
||||||
|
string value;
|
||||||
|
|
||||||
|
if (type == typeof(Point))
|
||||||
|
{
|
||||||
|
Point point = (Point)obj;
|
||||||
|
value = "X:" + point.X + "; Y:" + point.Y;
|
||||||
|
}
|
||||||
|
else if (type == typeof(PointF))
|
||||||
|
{
|
||||||
|
PointF point = (PointF)obj;
|
||||||
|
value = "X:" + point.X + "; Y:" + point.Y;
|
||||||
|
}
|
||||||
|
else if (type == typeof(Color))
|
||||||
|
{
|
||||||
|
Color color = (Color)obj;
|
||||||
|
value = "A:" + color.A + "; R:" + color.R + "; G:" + color.G + "; B:" + color.B;
|
||||||
|
}
|
||||||
|
else if (type == typeof(Size))
|
||||||
|
{
|
||||||
|
Size size = (Size)obj;
|
||||||
|
value = "W:" + size.Width + "; H:" + size.Height;
|
||||||
|
}
|
||||||
|
else if (type == typeof(SizeF))
|
||||||
|
{
|
||||||
|
SizeF size = (SizeF)obj;
|
||||||
|
value = "W:" + size.Width + "; H:" + size.Height;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new ApplicationException("不支持此类型: " + type.FullName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
382
SunnyUI/Common/UDateTimeInt64.cs
Normal file
382
SunnyUI/Common/UDateTimeInt64.cs
Normal file
@ -0,0 +1,382 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* SunnyUI 开源控件库、工具类库、扩展类库、多页面开发框架。
|
||||||
|
* CopyRight (C) 2012-2023 ShenYongHua(沈永华).
|
||||||
|
* QQ群:56829229 QQ:17612584 EMail:SunnyUI@QQ.Com
|
||||||
|
*
|
||||||
|
* Blog: https://www.cnblogs.com/yhuse
|
||||||
|
* Gitee: https://gitee.com/yhuse/SunnyUI
|
||||||
|
* GitHub: https://github.com/yhuse/SunnyUI
|
||||||
|
*
|
||||||
|
* SunnyUI.dll can be used for free under the GPL-3.0 license.
|
||||||
|
* If you use this code, please keep this note.
|
||||||
|
* 如果您使用此代码,请保留此说明。
|
||||||
|
******************************************************************************
|
||||||
|
* 文件名称: UDateTimeInt64.cs
|
||||||
|
* 文件说明: 日期长整型
|
||||||
|
* 当前版本: V2.2
|
||||||
|
* 创建日期: 2020-09-23
|
||||||
|
*
|
||||||
|
* 2020-09-23: V2.2.8 增加文件说明
|
||||||
|
* 2020-10-10: V2.2.8 增加与Double互转
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Sunny.UI
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 日期与长整形和浮点型互转
|
||||||
|
/// Value:长整形,为1970年1月1日0时起的毫秒数
|
||||||
|
/// DoubleValue:双精度浮点数,1970年1月1日0时起的天数
|
||||||
|
/// </summary>
|
||||||
|
public struct DateTimeInt64 : IComparable, IEquatable<DateTimeInt64>, IEquatable<long>, IEquatable<DateTime>
|
||||||
|
{
|
||||||
|
public long Value { get; set; }
|
||||||
|
|
||||||
|
public const long Jan1st1970Ticks = 621355968000000000; //Jan1st1970.Ticks;
|
||||||
|
public const long Dec31th9999Ticks = 3155378975999990000; //DateTime.MaxValue.Ticks;
|
||||||
|
public const string DefaultFormatString = DateTimeEx.DateTimeFormatEx;
|
||||||
|
public const double MillisecondsPerDay = 86400000.0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 返回当前时间的毫秒数, 这个毫秒其实就是自1970年1月1日0时起的毫秒数
|
||||||
|
/// </summary>
|
||||||
|
public static long CurrentDateTimeToTicks()
|
||||||
|
{
|
||||||
|
return (DateTime.UtcNow.Ticks - Jan1st1970Ticks) / 10000;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double DoubleValue
|
||||||
|
{
|
||||||
|
get { return Value * 1.0 / MillisecondsPerDay; }
|
||||||
|
set { Value = (long)(value * MillisecondsPerDay); }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 返回指定时间的毫秒数, 这个毫秒其实就是自1970年1月1日0时起的毫秒数
|
||||||
|
/// </summary>
|
||||||
|
public static long DateTimeToTicks(DateTime datetime)
|
||||||
|
{
|
||||||
|
return (datetime.ToUniversalTime().Ticks - Jan1st1970Ticks) / 10000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 从一个代表自1970年1月1日0时起的毫秒数,转换为DateTime (北京时间)
|
||||||
|
/// </summary>
|
||||||
|
public static DateTime TicksToDateTime(long ticks)
|
||||||
|
{
|
||||||
|
#pragma warning disable CS0618 // 类型或成员已过时
|
||||||
|
return TimeZone.CurrentTimeZone.ToLocalTime(TicksToUTCDateTime(ticks));
|
||||||
|
#pragma warning restore CS0618 // 类型或成员已过时
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 从一个代表自1970年1月1日0时起的毫秒数,转换为DateTime (UTC时间)
|
||||||
|
/// </summary>
|
||||||
|
public static DateTime TicksToUTCDateTime(long ticks)
|
||||||
|
{
|
||||||
|
return new DateTime(ticks * 10000 + Jan1st1970Ticks);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DateTimeInt64(long ticks)
|
||||||
|
{
|
||||||
|
ticks = MakeValidDate(ticks);
|
||||||
|
Value = ticks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DateTimeInt64(double doubleTicks)
|
||||||
|
{
|
||||||
|
doubleTicks = MakeValidDate((long)(doubleTicks * MillisecondsPerDay));
|
||||||
|
Value = (long)doubleTicks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DateTimeInt64(DateTime dateTime)
|
||||||
|
{
|
||||||
|
Value = DateTimeToTicks(dateTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DateTimeInt64(int year, int month, int day)
|
||||||
|
{
|
||||||
|
Value = DateTimeToTicks(new DateTime(year, month, day));
|
||||||
|
}
|
||||||
|
|
||||||
|
public DateTimeInt64(int year, int month, int day, int hour, int minute, int second)
|
||||||
|
{
|
||||||
|
Value = DateTimeToTicks(new DateTime(year, month, day, hour, minute, second));
|
||||||
|
}
|
||||||
|
|
||||||
|
public DateTimeInt64(int year, int month, int day, int hour, int minute, int second, int millisecond)
|
||||||
|
{
|
||||||
|
Value = DateTimeToTicks(new DateTime(year, month, day, hour, minute, second, millisecond));
|
||||||
|
}
|
||||||
|
|
||||||
|
public DateTimeInt64(DateTimeInt64 dtValue)
|
||||||
|
{
|
||||||
|
Value = dtValue.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsValidDate
|
||||||
|
{
|
||||||
|
get { return Value >= 0 && Value <= Dec31th9999Ticks - Jan1st1970Ticks; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public DateTime DateTime
|
||||||
|
{
|
||||||
|
get { return TicksToDateTime(Value); }
|
||||||
|
set { Value = DateTimeToTicks(value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool CheckValidDate(long ticks)
|
||||||
|
{
|
||||||
|
return ticks >= 0 && ticks <= Dec31th9999Ticks - Jan1st1970Ticks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long MakeValidDate(long ticks)
|
||||||
|
{
|
||||||
|
if (ticks < 0)
|
||||||
|
ticks = 0;
|
||||||
|
if (ticks > Dec31th9999Ticks - Jan1st1970Ticks)
|
||||||
|
ticks = Dec31th9999Ticks - Jan1st1970Ticks;
|
||||||
|
|
||||||
|
return ticks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddMilliseconds(double milliseconds)
|
||||||
|
{
|
||||||
|
Value = DateTimeToTicks(DateTime.AddMilliseconds(milliseconds));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddSeconds(double seconds)
|
||||||
|
{
|
||||||
|
Value = DateTimeToTicks(DateTime.AddSeconds(seconds));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddMinutes(double minutes)
|
||||||
|
{
|
||||||
|
Value = DateTimeToTicks(DateTime.AddMinutes(minutes));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddHours(double hours)
|
||||||
|
{
|
||||||
|
Value = DateTimeToTicks(DateTime.AddHours(hours));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddDays(double days)
|
||||||
|
{
|
||||||
|
Value = DateTimeToTicks(DateTime.AddDays(days));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddMonths(int months)
|
||||||
|
{
|
||||||
|
Value = DateTimeToTicks(DateTime.AddMonths(months));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddYears(int years)
|
||||||
|
{
|
||||||
|
Value = DateTimeToTicks(DateTime.AddYears(years));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long operator -(DateTimeInt64 dtValue1, DateTimeInt64 dtValue2)
|
||||||
|
{
|
||||||
|
return dtValue1.Value - dtValue2.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long operator +(DateTimeInt64 dtValue1, DateTimeInt64 dtValue2)
|
||||||
|
{
|
||||||
|
return dtValue1.Value + dtValue2.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DateTimeInt64 operator -(DateTimeInt64 dtValue1, long dtValue2)
|
||||||
|
{
|
||||||
|
dtValue1.Value -= dtValue2;
|
||||||
|
return dtValue1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DateTimeInt64 operator +(DateTimeInt64 dtValue1, long dtValue2)
|
||||||
|
{
|
||||||
|
dtValue1.Value += dtValue2;
|
||||||
|
return dtValue1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DateTimeInt64 operator ++(DateTimeInt64 dtValue)
|
||||||
|
{
|
||||||
|
dtValue.AddDays(1);
|
||||||
|
return dtValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DateTimeInt64 operator --(DateTimeInt64 dtValue)
|
||||||
|
{
|
||||||
|
dtValue.AddDays(-1);
|
||||||
|
return dtValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator long(DateTimeInt64 dtValue)
|
||||||
|
{
|
||||||
|
return dtValue.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator DateTimeInt64(long ticks)
|
||||||
|
{
|
||||||
|
return new DateTimeInt64(ticks);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator DateTimeInt64(DateTime dt)
|
||||||
|
{
|
||||||
|
return new DateTimeInt64(dt);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator DateTime(DateTimeInt64 dt)
|
||||||
|
{
|
||||||
|
return dt.DateTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator double(DateTimeInt64 dtValue)
|
||||||
|
{
|
||||||
|
return dtValue.DoubleValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static implicit operator DateTimeInt64(double ticks)
|
||||||
|
{
|
||||||
|
return new DateTimeInt64(ticks);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(DateTimeInt64 dtValue1, DateTimeInt64 dtValue2)
|
||||||
|
{
|
||||||
|
return dtValue1.Value == dtValue2.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator !=(DateTimeInt64 dtValue1, DateTimeInt64 dtValue2)
|
||||||
|
{
|
||||||
|
return dtValue1.Value != dtValue2.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(DateTimeInt64 dtValue, long ticks)
|
||||||
|
{
|
||||||
|
return dtValue.Value == ticks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator !=(DateTimeInt64 dtValue, long ticks)
|
||||||
|
{
|
||||||
|
return dtValue.Value != ticks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator <(DateTimeInt64 dtValue1, DateTimeInt64 dtValue2)
|
||||||
|
{
|
||||||
|
return dtValue1.Value < dtValue2.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator >(DateTimeInt64 dtValue1, DateTimeInt64 dtValue2)
|
||||||
|
{
|
||||||
|
return dtValue1.Value > dtValue2.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator <=(DateTimeInt64 dtValue1, DateTimeInt64 dtValue2)
|
||||||
|
{
|
||||||
|
return dtValue1.Value <= dtValue2.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator >=(DateTimeInt64 dtValue1, DateTimeInt64 dtValue2)
|
||||||
|
{
|
||||||
|
return dtValue1.Value >= dtValue2.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator <(DateTimeInt64 dtValue, long ticks)
|
||||||
|
{
|
||||||
|
return dtValue.Value < ticks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator >(DateTimeInt64 dtValue, long ticks)
|
||||||
|
{
|
||||||
|
return dtValue.Value > ticks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator <=(DateTimeInt64 dtValue, long ticks)
|
||||||
|
{
|
||||||
|
return dtValue.Value <= ticks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator >=(DateTimeInt64 dtValue, long ticks)
|
||||||
|
{
|
||||||
|
return dtValue.Value >= ticks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
if (obj is DateTimeInt64 dtValue)
|
||||||
|
{
|
||||||
|
return dtValue.Value == Value;
|
||||||
|
}
|
||||||
|
else if (obj is long longValue)
|
||||||
|
{
|
||||||
|
return longValue == Value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return Value.GetHashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
int IComparable.CompareTo(object obj)
|
||||||
|
{
|
||||||
|
if (!(obj is DateTimeInt64)) throw new ArgumentException();
|
||||||
|
return (Value).CompareTo(((DateTimeInt64)obj).Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ToString(long ticks)
|
||||||
|
{
|
||||||
|
return ToString(ticks, DefaultFormatString);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return ToString(Value, DefaultFormatString);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ToString(string fmtStr)
|
||||||
|
{
|
||||||
|
return ToString(Value, fmtStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string ToString(long dtValue, string fmtStr)
|
||||||
|
{
|
||||||
|
DateTime dt = TicksToDateTime(dtValue);
|
||||||
|
return dt.ToString(fmtStr);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(DateTimeInt64 dtValue)
|
||||||
|
{
|
||||||
|
return Value == dtValue.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(long ticks)
|
||||||
|
{
|
||||||
|
return Value == ticks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(DateTime datetime)
|
||||||
|
{
|
||||||
|
return Value == (new DateTimeInt64(datetime)).Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string DateTimeString => DateTime.DateTimeString();
|
||||||
|
|
||||||
|
public string DateString => DateTime.DateString();
|
||||||
|
|
||||||
|
public string TimeString => DateTime.TimeString();
|
||||||
|
|
||||||
|
public string HourMinuteString => DateTime.ToString("HH:mm");
|
||||||
|
|
||||||
|
public int Year => DateTime.Year;
|
||||||
|
public int Month => DateTime.Month;
|
||||||
|
public int Day => DateTime.Day;
|
||||||
|
public int Hour => DateTime.Hour;
|
||||||
|
public int Minute => DateTime.Minute;
|
||||||
|
public int Second => DateTime.Second;
|
||||||
|
public int Millisecond => DateTime.Millisecond;
|
||||||
|
}
|
||||||
|
}
|
@ -22,7 +22,6 @@
|
|||||||
* 2023-08-11: v3.4.1 增加了文件绝对路径判断和文件夹是否存在判断
|
* 2023-08-11: v3.4.1 增加了文件绝对路径判断和文件夹是否存在判断
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
using Sunny.UI.Win32;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
@ -31,6 +30,7 @@ using System.Globalization;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using Sunny.UI.Win32;
|
||||||
|
|
||||||
namespace Sunny.UI
|
namespace Sunny.UI
|
||||||
{
|
{
|
||||||
@ -299,29 +299,6 @@ namespace Sunny.UI
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class IniFile : IniBase
|
public class IniFile : IniBase
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// 写Byte数组
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="section">section</param>
|
|
||||||
/// <param name="key">key</param>
|
|
||||||
/// <param name="value">value</param>
|
|
||||||
public void Write(string section, string key, byte[] value)
|
|
||||||
{
|
|
||||||
Write(section, key, value.ToHexString());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// 读Byte数组
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="section">section</param>
|
|
||||||
/// <param name="key">key</param>
|
|
||||||
/// <param name="Default">Normal</param>
|
|
||||||
/// <returns>结果</returns>
|
|
||||||
public byte[] ReadBytes(string section, string key, byte[] Default)
|
|
||||||
{
|
|
||||||
return Read(section, key, Default.ToHexString()).ToHexBytes();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 写Char
|
/// 写Char
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
790
SunnyUI/Common/UIniFileEx.cs
Normal file
790
SunnyUI/Common/UIniFileEx.cs
Normal file
@ -0,0 +1,790 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* SunnyUI 开源控件库、工具类库、扩展类库、多页面开发框架。
|
||||||
|
* CopyRight (C) 2012-2023 ShenYongHua(沈永华).
|
||||||
|
* QQ群:56829229 QQ:17612584 EMail:SunnyUI@QQ.Com
|
||||||
|
*
|
||||||
|
* Blog: https://www.cnblogs.com/yhuse
|
||||||
|
* Gitee: https://gitee.com/yhuse/SunnyUI
|
||||||
|
* GitHub: https://github.com/yhuse/SunnyUI
|
||||||
|
*
|
||||||
|
* SunnyUI.dll can be used for free under the GPL-3.0 license.
|
||||||
|
* If you use this code, please keep this note.
|
||||||
|
* 如果您使用此代码,请保留此说明。
|
||||||
|
******************************************************************************
|
||||||
|
* 文件名称: UIniFileEx.cs
|
||||||
|
* 文件说明: INI 文件读取类(不用WinAPI)
|
||||||
|
* 当前版本: V3.1
|
||||||
|
* 创建日期: 2021-10-27
|
||||||
|
*
|
||||||
|
* 2021-10-27: V2.2.0 增加文件说明
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Specialized;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Drawing;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace Sunny.UI
|
||||||
|
{
|
||||||
|
public class IniFileEx
|
||||||
|
{
|
||||||
|
private readonly Dictionary<string, NameValueCollection> data = new Dictionary<string, NameValueCollection>();
|
||||||
|
|
||||||
|
private static readonly Regex regRemoveEmptyLines =
|
||||||
|
new Regex
|
||||||
|
(
|
||||||
|
@"(\s*;[\d\D]*?\r?\n)+|\r?\n(\s*\r?\n)*",
|
||||||
|
RegexOptions.Multiline | RegexOptions.Compiled
|
||||||
|
);
|
||||||
|
|
||||||
|
private static readonly Regex regParseIniData =
|
||||||
|
new Regex
|
||||||
|
(
|
||||||
|
@"
|
||||||
|
(?<IsSection>
|
||||||
|
^\s*\[(?<SectionName>[^\]]+)?\]\s*$
|
||||||
|
)
|
||||||
|
|
|
||||||
|
(?<IsKeyValue>
|
||||||
|
^\s*(?<Key>[^(\s*\=\s*)]+)?\s*\=\s*(?<Value>[\d\D]*)$
|
||||||
|
)",
|
||||||
|
RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace
|
||||||
|
);
|
||||||
|
|
||||||
|
public IniFileEx(string fileName) : this(fileName, Encoding.Default) { }
|
||||||
|
|
||||||
|
public IniFileEx(string fileName, Encoding encoding)
|
||||||
|
{
|
||||||
|
FileName = fileName;
|
||||||
|
Encoding = encoding;
|
||||||
|
using FileStream fs = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
|
||||||
|
ReadIniData(fs, encoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 文件名
|
||||||
|
/// </summary>
|
||||||
|
[Description("文件名")]
|
||||||
|
public string FileName { get; set; } //INI文件名
|
||||||
|
|
||||||
|
public Encoding Encoding { get; set; }
|
||||||
|
|
||||||
|
private void ReadIniData(Stream stream, Encoding encoding)
|
||||||
|
{
|
||||||
|
string lastSection = string.Empty;
|
||||||
|
data.Add(lastSection, new NameValueCollection());
|
||||||
|
if (stream != null && encoding != null)
|
||||||
|
{
|
||||||
|
using StreamReader reader = new StreamReader(stream, encoding);
|
||||||
|
string iniData = reader.ReadToEnd();
|
||||||
|
|
||||||
|
iniData = regRemoveEmptyLines.Replace(iniData, "\n");
|
||||||
|
string[] lines = iniData.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
|
||||||
|
foreach (string s in lines)
|
||||||
|
{
|
||||||
|
Match m = regParseIniData.Match(s);
|
||||||
|
if (m.Success)
|
||||||
|
{
|
||||||
|
if (m.Groups["IsSection"].Length > 0)
|
||||||
|
{
|
||||||
|
string sName = m.Groups["SectionName"].Value.ToLowerInvariant();
|
||||||
|
if (lastSection != sName)
|
||||||
|
{
|
||||||
|
lastSection = sName;
|
||||||
|
if (!data.ContainsKey(sName))
|
||||||
|
{
|
||||||
|
data.Add(sName, new NameValueCollection());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (m.Groups["IsKeyValue"].Length > 0)
|
||||||
|
{
|
||||||
|
data[lastSection].Add(m.Groups["Key"].Value, m.Groups["Value"].Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public NameValueCollection this[string section]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
section = section.ToLowerInvariant();
|
||||||
|
if (!data.ContainsKey(section))
|
||||||
|
data.Add(section, new NameValueCollection());
|
||||||
|
return data[section];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string this[string section, string key]
|
||||||
|
{
|
||||||
|
get => this[section][key];
|
||||||
|
set => this[section][key] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public object this[string section, string key, Type t]
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (t == null || t == (Type)Type.Missing)
|
||||||
|
return this[section][key];
|
||||||
|
return GetValue(section, key, null, t);
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (t == null || t == (Type)Type.Missing)
|
||||||
|
this[section][key] = string.Empty;
|
||||||
|
else
|
||||||
|
SetValue(section, key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string[] KeyNames(string section)
|
||||||
|
{
|
||||||
|
return this[section].AllKeys;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string[] SectionValues(string section)
|
||||||
|
{
|
||||||
|
return this[section].GetValues(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private object GetValue(string section, string key, object defaultValue, Type t)
|
||||||
|
{
|
||||||
|
section = section.ToLowerInvariant();
|
||||||
|
key = key.ToLowerInvariant();
|
||||||
|
if (!data.ContainsKey(section)) return defaultValue;
|
||||||
|
string v = data[section][key];
|
||||||
|
if (string.IsNullOrEmpty(v)) return defaultValue;
|
||||||
|
TypeConverter conv = TypeDescriptor.GetConverter(t);
|
||||||
|
if (!conv.CanConvertFrom(typeof(string))) return defaultValue;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return conv.ConvertFrom(v);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private T GetValue<T>(string section, string key, T defaultValue)
|
||||||
|
{
|
||||||
|
return (T)GetValue(section, key, defaultValue, typeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetValue(string section, string key, object value)
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
this[section][key] = string.Empty;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TypeConverter conv = TypeDescriptor.GetConverter(value);
|
||||||
|
if (!conv.CanConvertTo(typeof(string)))
|
||||||
|
{
|
||||||
|
this[section][key] = value.ToString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this[section][key] = (string)conv.ConvertTo(value, typeof(string));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Write(string section, string key, string value)
|
||||||
|
{
|
||||||
|
SetValue(section, key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Read(string section, string key, string Default)
|
||||||
|
{
|
||||||
|
return GetValue(section, key, Default);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读取指定的Section的所有Value到列表中
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
public NameValueCollection GetSectionValues(string section)
|
||||||
|
{
|
||||||
|
return this[section];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateFile()
|
||||||
|
{
|
||||||
|
Save();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Save()
|
||||||
|
{
|
||||||
|
Save(FileName, Encoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Save(string fileName, Encoding encoding)
|
||||||
|
{
|
||||||
|
using FileStream fs = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
|
||||||
|
Save(fs, encoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Save(Stream stream, Encoding encoding)
|
||||||
|
{
|
||||||
|
using StreamWriter sw = new StreamWriter(stream, encoding);
|
||||||
|
foreach (var cur in data)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(cur.Key))
|
||||||
|
{
|
||||||
|
sw.WriteLine("[{0}]", cur.Key);
|
||||||
|
}
|
||||||
|
|
||||||
|
NameValueCollection col = cur.Value;
|
||||||
|
foreach (string key in col.Keys)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(key))
|
||||||
|
{
|
||||||
|
string value = col[key];
|
||||||
|
if (!string.IsNullOrEmpty(value))
|
||||||
|
sw.WriteLine("{0}={1}", key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sw.Flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HasSection(string section)
|
||||||
|
{
|
||||||
|
return data.ContainsKey(section.ToLowerInvariant());
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool HasKey(string section, string key)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
data.ContainsKey(section) &&
|
||||||
|
!string.IsNullOrEmpty(data[section][key]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 写结构
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="value">value</param>
|
||||||
|
/// <typeparam name="T">T</typeparam>
|
||||||
|
public void WriteStruct<T>(string section, string key, T value) where T : struct
|
||||||
|
{
|
||||||
|
Write(section, key, value.ToBytes());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读结构
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">T</typeparam>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="Default">Normal</param>
|
||||||
|
/// <returns>结果</returns>
|
||||||
|
public T ReadStruct<T>(string section, string key, T Default) where T : struct
|
||||||
|
{
|
||||||
|
//得到结构体的大小
|
||||||
|
int size = StructEx.Size(Default);
|
||||||
|
byte[] bytes = Read(section, key, "").ToHexBytes();
|
||||||
|
return size > bytes.Length ? Default : bytes.ToStruct<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 写Byte数组
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="value">value</param>
|
||||||
|
public void Write(string section, string key, byte[] value)
|
||||||
|
{
|
||||||
|
Write(section, key, value.ToHexString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读Byte数组
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="Default">Normal</param>
|
||||||
|
/// <returns>结果</returns>
|
||||||
|
public byte[] ReadBytes(string section, string key, byte[] Default)
|
||||||
|
{
|
||||||
|
return Read(section, key, Default.ToHexString()).ToHexBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 写Char
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="value">value</param>
|
||||||
|
public void Write(string section, string key, char value)
|
||||||
|
{
|
||||||
|
Write(section, key, value.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读Char
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="Default">Normal</param>
|
||||||
|
/// <returns>结果</returns>
|
||||||
|
public char ReadChar(string section, string key, char Default = ' ')
|
||||||
|
{
|
||||||
|
return Read(section, key, Default.ToString()).ToChar(Default);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 写Decimal
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="value">value</param>
|
||||||
|
public void Write(string section, string key, decimal value)
|
||||||
|
{
|
||||||
|
Write(section, key, value.ToString(CultureInfo.InvariantCulture));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读Decimal
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="Default">Normal</param>
|
||||||
|
/// <returns>结果</returns>
|
||||||
|
public decimal ReadDecimal(string section, string key, decimal Default = 0)
|
||||||
|
{
|
||||||
|
return Read(section, key, Default.ToString(CultureInfo.InvariantCulture)).ToDecimal(Default);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 写整数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="value">value</param>
|
||||||
|
public void Write(string section, string key, short value)
|
||||||
|
{
|
||||||
|
Write(section, key, value.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读整数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="Default">Normal</param>
|
||||||
|
/// <returns>结果</returns>
|
||||||
|
public short ReadShort(string section, string key, short Default = 0)
|
||||||
|
{
|
||||||
|
return Read(section, key, Default.ToString()).ToShort(Default);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 写整数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="value">value</param>
|
||||||
|
public void Write(string section, string key, ushort value)
|
||||||
|
{
|
||||||
|
Write(section, key, value.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读整数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="Default">Normal</param>
|
||||||
|
/// <returns>结果</returns>
|
||||||
|
public ushort ReadUShort(string section, string key, ushort Default = 0)
|
||||||
|
{
|
||||||
|
return Read(section, key, Default.ToString()).ToUShort(Default);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 写整数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="value">value</param>
|
||||||
|
public void Write(string section, string key, int value)
|
||||||
|
{
|
||||||
|
Write(section, key, value.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读整数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="Default">Normal</param>
|
||||||
|
/// <returns>结果</returns>
|
||||||
|
public int ReadInt(string section, string key, int Default = 0)
|
||||||
|
{
|
||||||
|
return Read(section, key, Default.ToString()).ToInt(Default);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 写整数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="value">value</param>
|
||||||
|
public void Write(string section, string key, uint value)
|
||||||
|
{
|
||||||
|
Write(section, key, value.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读整数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="Default">Normal</param>
|
||||||
|
/// <returns>结果</returns>
|
||||||
|
public uint ReadUInt(string section, string key, uint Default = 0)
|
||||||
|
{
|
||||||
|
return Read(section, key, Default.ToString()).ToUInt(Default);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 写整数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="value">value</param>
|
||||||
|
public void Write(string section, string key, ulong value)
|
||||||
|
{
|
||||||
|
Write(section, key, value.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读整数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="Default">Normal</param>
|
||||||
|
/// <returns>结果</returns>
|
||||||
|
public ulong ReadULong(string section, string key, ulong Default = 0)
|
||||||
|
{
|
||||||
|
return Read(section, key, Default.ToString()).ToULong(Default);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 写整数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="value">value</param>
|
||||||
|
public void Write(string section, string key, long value)
|
||||||
|
{
|
||||||
|
Write(section, key, value.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读整数
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="Default">Normal</param>
|
||||||
|
/// <returns>结果</returns>
|
||||||
|
public long ReadLong(string section, string key, long Default = 0)
|
||||||
|
{
|
||||||
|
return Read(section, key, Default.ToString()).ToLong(Default);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 写布尔
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="value">value</param>
|
||||||
|
public void Write(string section, string key, bool value)
|
||||||
|
{
|
||||||
|
Write(section, key, value ? bool.TrueString : bool.FalseString);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读布尔
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="Default">Normal</param>
|
||||||
|
/// <returns>结果</returns>
|
||||||
|
public bool ReadBool(string section, string key, bool Default = false)
|
||||||
|
{
|
||||||
|
string str = Read(section, key, Default.ToString());
|
||||||
|
if (string.Equals(str, bool.TrueString, StringComparison.CurrentCultureIgnoreCase))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (string.Equals(str, bool.FalseString, StringComparison.CurrentCultureIgnoreCase))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Default;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 写Double
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="value">value</param>
|
||||||
|
public void Write(string section, string key, double value)
|
||||||
|
{
|
||||||
|
Write(section, key, value.ToString(CultureInfo.InvariantCulture));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读Double
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="Default">Normal</param>
|
||||||
|
/// <returns>结果</returns>
|
||||||
|
public double ReadDouble(string section, string key, double Default = 0)
|
||||||
|
{
|
||||||
|
return Read(section, key, Default.ToString(CultureInfo.InvariantCulture)).ToDouble(Default);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 写Float
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="value">value</param>
|
||||||
|
public void Write(string section, string key, float value)
|
||||||
|
{
|
||||||
|
Write(section, key, value.ToString(CultureInfo.InvariantCulture));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读Float
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="Default">Normal</param>
|
||||||
|
/// <returns>结果</returns>
|
||||||
|
public float ReadFloat(string section, string key, float Default = 0)
|
||||||
|
{
|
||||||
|
return Read(section, key, Default.ToString(CultureInfo.InvariantCulture)).ToFloat(Default);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 写Byte
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="value">value</param>
|
||||||
|
public void Write(string section, string key, byte value)
|
||||||
|
{
|
||||||
|
Write(section, key, value.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读Byte
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="Default">Normal</param>
|
||||||
|
/// <returns>结果</returns>
|
||||||
|
public byte ReadByte(string section, string key, byte Default = 0)
|
||||||
|
{
|
||||||
|
return Read(section, key, Default.ToString()).ToByte(Default);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 写SByte
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="value">value</param>
|
||||||
|
public void Write(string section, string key, sbyte value)
|
||||||
|
{
|
||||||
|
Write(section, key, value.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读Byte
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="Default">Normal</param>
|
||||||
|
/// <returns>结果</returns>
|
||||||
|
public sbyte ReadSByte(string section, string key, sbyte Default = 0)
|
||||||
|
{
|
||||||
|
return Read(section, key, Default.ToString()).ToSByte(Default);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 写DateTime
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="value">value</param>
|
||||||
|
public void Write(string section, string key, DateTime value)
|
||||||
|
{
|
||||||
|
Write(section, key, value.ToString(DateTimeEx.DateTimeFormat));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读DateTime
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="Default">Normal</param>
|
||||||
|
/// <returns>结果</returns>
|
||||||
|
public DateTime ReadDateTime(string section, string key, DateTime Default)
|
||||||
|
{
|
||||||
|
string str = Read(section, key, Default.ToString(CultureInfo.InvariantCulture));
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return str.ToDateTime(DateTimeEx.DateTimeFormat);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
return Default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 写Point
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="value">value</param>
|
||||||
|
public void Write(string section, string key, Point value)
|
||||||
|
{
|
||||||
|
Write(section, key, ConvertEx.ObjectToString(value, typeof(Point)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读Point
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="Default">Normal</param>
|
||||||
|
/// <returns>结果</returns>
|
||||||
|
public Point ReadPoint(string section, string key, Point Default)
|
||||||
|
{
|
||||||
|
string str = Read(section, key, "");
|
||||||
|
return (Point)ConvertEx.StringToObject(str, typeof(Point), Default);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 写PointF
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="value">value</param>
|
||||||
|
public void Write(string section, string key, PointF value)
|
||||||
|
{
|
||||||
|
Write(section, key, ConvertEx.ObjectToString(value, typeof(PointF)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读PointF
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="Default">Normal</param>
|
||||||
|
/// <returns>结果</returns>
|
||||||
|
public PointF ReadPointF(string section, string key, PointF Default)
|
||||||
|
{
|
||||||
|
string str = Read(section, key, "");
|
||||||
|
return (PointF)ConvertEx.StringToObject(str, typeof(PointF), Default);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 写Size
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="value">value</param>
|
||||||
|
public void Write(string section, string key, Size value)
|
||||||
|
{
|
||||||
|
Write(section, key, ConvertEx.ObjectToString(value, typeof(Size)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读Size
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="Default">Normal</param>
|
||||||
|
/// <returns>结果</returns>
|
||||||
|
public Size ReadSize(string section, string key, Size Default)
|
||||||
|
{
|
||||||
|
string str = Read(section, key, "");
|
||||||
|
return (Size)ConvertEx.StringToObject(str, typeof(Size), Default);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 写SizeF
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="value">value</param>
|
||||||
|
public void Write(string section, string key, SizeF value)
|
||||||
|
{
|
||||||
|
Write(section, key, ConvertEx.ObjectToString(value, typeof(SizeF)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读SizeF
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="Default">Normal</param>
|
||||||
|
/// <returns>结果</returns>
|
||||||
|
public SizeF ReadSizeF(string section, string key, SizeF Default)
|
||||||
|
{
|
||||||
|
string str = Read(section, key, "");
|
||||||
|
return (SizeF)ConvertEx.StringToObject(str, typeof(SizeF), Default);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 写Color
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="value">value</param>
|
||||||
|
public void Write(string section, string key, Color value)
|
||||||
|
{
|
||||||
|
Write(section, key, ConvertEx.ObjectToString(value, typeof(Color)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读Color
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="section">section</param>
|
||||||
|
/// <param name="key">key</param>
|
||||||
|
/// <param name="Default">Normal</param>
|
||||||
|
/// <returns>结果</returns>
|
||||||
|
public Color ReadColor(string section, string key, Color Default)
|
||||||
|
{
|
||||||
|
string str = Read(section, key, "");
|
||||||
|
return (Color)ConvertEx.StringToObject(str, typeof(Color), Default);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
203
SunnyUI/Common/UMapper.cs
Normal file
203
SunnyUI/Common/UMapper.cs
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* SunnyUI 开源控件库、工具类库、扩展类库、多页面开发框架。
|
||||||
|
* CopyRight (C) 2012-2023 ShenYongHua(沈永华).
|
||||||
|
* QQ群:56829229 QQ:17612584 EMail:SunnyUI@QQ.Com
|
||||||
|
*
|
||||||
|
* Blog: https://www.cnblogs.com/yhuse
|
||||||
|
* Gitee: https://gitee.com/yhuse/SunnyUI
|
||||||
|
* GitHub: https://github.com/yhuse/SunnyUI
|
||||||
|
*
|
||||||
|
* SunnyUI.dll can be used for free under the GPL-3.0 license.
|
||||||
|
* If you use this code, please keep this note.
|
||||||
|
* 如果您使用此代码,请保留此说明。
|
||||||
|
******************************************************************************
|
||||||
|
* 文件名称: UMapper.cs
|
||||||
|
* 文件说明: 轻量级的对象映射框架,可以映射值类型(包括Struct),和以值类型构成的List和数组。
|
||||||
|
* 当前版本: V3.1
|
||||||
|
* 创建日期: 2021-09-30
|
||||||
|
*
|
||||||
|
* 2021-09-30: V3.0.7 增加文件说明
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace Sunny.UI
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 轻量级的对象映射框架
|
||||||
|
/// </summary>
|
||||||
|
public static class Mapper
|
||||||
|
{
|
||||||
|
private static void Execute<T1, T2>(T1 source, T2 dest)
|
||||||
|
where T1 : class, new()
|
||||||
|
where T2 : class, new()
|
||||||
|
{
|
||||||
|
if (source == null || dest == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var listSource = source.GetType().GetNeedProperties().ToDictionary(prop => prop.Name);
|
||||||
|
var listDest = dest.GetType().GetNeedProperties().ToDictionary(prop => prop.Name);
|
||||||
|
|
||||||
|
foreach (var item in listDest)
|
||||||
|
{
|
||||||
|
if (listSource.NotContainsKey(item.Key)) continue;
|
||||||
|
|
||||||
|
var sourceInfo = listSource[item.Key];
|
||||||
|
Type sourceType = sourceInfo.PropertyType;
|
||||||
|
object sourceValue = sourceInfo.GetValue(source, null);
|
||||||
|
|
||||||
|
var destInfo = item.Value;
|
||||||
|
Type destType = item.Value.PropertyType;
|
||||||
|
|
||||||
|
if (!sourceType.Equals(destType)) continue;
|
||||||
|
if (sourceType.IsValueType)
|
||||||
|
{
|
||||||
|
//Console.WriteLine("ValueType: " + item.Key + ", " + sourceType.FullName);
|
||||||
|
destInfo.SetValue(dest, sourceValue, null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (sourceType == typeof(string))
|
||||||
|
{
|
||||||
|
//Console.WriteLine("String: " + item.Key + ", " + sourceType.FullName);
|
||||||
|
destInfo.SetValue(dest, sourceValue, null);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sourceType.IsList())
|
||||||
|
{
|
||||||
|
//Console.WriteLine("List: " + item.Key + ", " + sourceType.FullName);
|
||||||
|
Type[] sourceTypes = sourceType.GetGenericArguments();
|
||||||
|
Type[] destTypes = destType.GetGenericArguments();
|
||||||
|
if (sourceTypes.Length != 1) continue;
|
||||||
|
if (destTypes.Length != 1) continue;
|
||||||
|
if (!sourceTypes[0].Equals(destTypes[0])) continue;
|
||||||
|
|
||||||
|
if (sourceValue == null)
|
||||||
|
{
|
||||||
|
destInfo.SetValue(dest, null, null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Type typeDataList = typeof(List<>).MakeGenericType(destTypes[0]);
|
||||||
|
MethodInfo AddInfo = typeDataList.GetMethod("Add", BindingFlags.Public | BindingFlags.Instance);
|
||||||
|
if (AddInfo == null) continue;
|
||||||
|
|
||||||
|
if (sourceTypes[0].IsValueType || sourceTypes[0] == typeof(string))
|
||||||
|
{
|
||||||
|
object listvalue = typeDataList.InvokeMember(null, BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.CreateInstance, null, null, new object[] { });
|
||||||
|
IEnumerable sourceList = sourceValue as IEnumerable;
|
||||||
|
foreach (var listItem in sourceList)
|
||||||
|
{
|
||||||
|
AddInfo.Invoke(listvalue, new[] { listItem });
|
||||||
|
}
|
||||||
|
|
||||||
|
destInfo.SetValue(dest, listvalue, null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//暂时不考虑
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sourceType.IsArray)
|
||||||
|
{
|
||||||
|
//Console.WriteLine("Array: " + item.Key + ", " + sourceType.FullName);
|
||||||
|
if (sourceValue == null)
|
||||||
|
{
|
||||||
|
destInfo.SetValue(dest, null, null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ICollection sourceList = sourceValue as ICollection;
|
||||||
|
Type type = sourceType.GetElementType();
|
||||||
|
var array = Array.CreateInstance(type, sourceList.Count);
|
||||||
|
|
||||||
|
int index = 0;
|
||||||
|
foreach (var listItem in sourceList)
|
||||||
|
{
|
||||||
|
array.SetValue(listItem, index++);
|
||||||
|
}
|
||||||
|
|
||||||
|
destInfo.SetValue(dest, array, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sourceType.IsDictionary())
|
||||||
|
{
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//类没有无参构造函数的话,创建有问题
|
||||||
|
//if (sourceType.IsClass)
|
||||||
|
//{
|
||||||
|
// if (sourceValue == null)
|
||||||
|
// {
|
||||||
|
// destInfo.SetValue(dest, null, null);
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// object obj = Activator.CreateInstance(sourceType, null);
|
||||||
|
// obj.MapperFrom(sourceValue);
|
||||||
|
// destInfo.SetValue(dest, obj, null);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// continue;
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// T1映射到T2
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T1">T1</typeparam>
|
||||||
|
/// <typeparam name="T2">T2</typeparam>
|
||||||
|
/// <param name="source">源</param>
|
||||||
|
/// <param name="dest">目标</param>
|
||||||
|
public static void MapperTo<T1, T2>(this T1 source, T2 dest)
|
||||||
|
where T1 : class, new()
|
||||||
|
where T2 : class, new()
|
||||||
|
{
|
||||||
|
Execute(source, dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// T1从T2映射
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T1">T1</typeparam>
|
||||||
|
/// <typeparam name="T2">T2</typeparam>
|
||||||
|
/// <param name="source">源</param>
|
||||||
|
/// <param name="dest">目标</param>
|
||||||
|
public static void MapperFrom<T1, T2>(this T1 dest, T2 source)
|
||||||
|
where T1 : class, new()
|
||||||
|
where T2 : class, new()
|
||||||
|
{
|
||||||
|
Execute(source, dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取数组的类类型
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="t">类型</param>
|
||||||
|
/// <returns>类类型</returns>
|
||||||
|
public static Type GetArrayElementType(this Type t)
|
||||||
|
{
|
||||||
|
if (!t.IsArray) return null;
|
||||||
|
string name = t.FullName.Replace("[]", string.Empty);
|
||||||
|
return t.Assembly.GetType(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -22,9 +22,9 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Windows.Forms;
|
|
||||||
|
|
||||||
#pragma warning disable 1591
|
#pragma warning disable 1591
|
||||||
|
|
||||||
@ -32,7 +32,7 @@ namespace Sunny.UI
|
|||||||
{
|
{
|
||||||
public class Thunder : IDisposable
|
public class Thunder : IDisposable
|
||||||
{
|
{
|
||||||
private readonly Timer timer;
|
private readonly System.Windows.Forms.Timer timer;
|
||||||
private bool Exit;
|
private bool Exit;
|
||||||
|
|
||||||
public delegate void OnTaskInfoChange(object sender, ThunderTask task);
|
public delegate void OnTaskInfoChange(object sender, ThunderTask task);
|
||||||
@ -52,7 +52,7 @@ namespace Sunny.UI
|
|||||||
public Thunder()
|
public Thunder()
|
||||||
{
|
{
|
||||||
InitSuccess = ThunderDll.Init();
|
InitSuccess = ThunderDll.Init();
|
||||||
timer = new Timer();
|
timer = new System.Windows.Forms.Timer();
|
||||||
timer.Interval = 1000;
|
timer.Interval = 1000;
|
||||||
timer.Tick += Timer_Tick;
|
timer.Tick += Timer_Tick;
|
||||||
timer.Start();
|
timer.Start();
|
||||||
@ -512,7 +512,7 @@ namespace Sunny.UI
|
|||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return Status.DisplayText() + ",已完成:" + (Percent * 100.0f).ToString("F2") + "%,速度:" + Speed + "KB/s";
|
return Status.Description() + ",已完成:" + (Percent * 100.0f).ToString("F2") + "%,速度:" + Speed + "KB/s";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -524,43 +524,43 @@ namespace Sunny.UI
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 无
|
/// 无
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DisplayText("无")]
|
[Description("无")]
|
||||||
NOITEM = 0,
|
NOITEM = 0,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 错误
|
/// 错误
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DisplayText("错误")]
|
[Description("错误")]
|
||||||
TSC_ERROR,
|
TSC_ERROR,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 暂停
|
/// 暂停
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DisplayText("暂停")]
|
[Description("暂停")]
|
||||||
TSC_PAUSE,
|
TSC_PAUSE,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 下载
|
/// 下载
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DisplayText("下载中")]
|
[Description("下载中")]
|
||||||
TSC_DOWNLOAD,
|
TSC_DOWNLOAD,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 完成
|
/// 完成
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DisplayText("完成")]
|
[Description("完成")]
|
||||||
TSC_COMPLETE,
|
TSC_COMPLETE,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 停止开始
|
/// 停止开始
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DisplayText("已开始")]
|
[Description("已开始")]
|
||||||
TSC_STARTENDING,
|
TSC_STARTENDING,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 停止完成
|
/// 停止完成
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DisplayText("已停止")]
|
[Description("已停止")]
|
||||||
TSC_STOPENDING
|
TSC_STOPENDING
|
||||||
}
|
}
|
||||||
|
|
||||||
|
163
SunnyUI/Common/UXmlConfig.cs
Normal file
163
SunnyUI/Common/UXmlConfig.cs
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* SunnyUI 开源控件库、工具类库、扩展类库、多页面开发框架。
|
||||||
|
* CopyRight (C) 2012-2023 ShenYongHua(沈永华).
|
||||||
|
* QQ群:56829229 QQ:17612584 EMail:SunnyUI@QQ.Com
|
||||||
|
*
|
||||||
|
* Blog: https://www.cnblogs.com/yhuse
|
||||||
|
* Gitee: https://gitee.com/yhuse/SunnyUI
|
||||||
|
* GitHub: https://github.com/yhuse/SunnyUI
|
||||||
|
*
|
||||||
|
* SunnyUI.Common.dll can be used for free under the MIT license.
|
||||||
|
* If you use this code, please keep this note.
|
||||||
|
* 如果您使用此代码,请保留此说明。
|
||||||
|
******************************************************************************
|
||||||
|
* 文件名称: UXmlConfig.cs
|
||||||
|
* 文件说明: XML 配置文件类
|
||||||
|
* 当前版本: V3.1
|
||||||
|
* 创建日期: 2020-01-01
|
||||||
|
*
|
||||||
|
* 2020-01-01: V2.2.0 增加文件说明
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using System.Xml;
|
||||||
|
|
||||||
|
namespace Sunny.UI
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// XML 配置文件类
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TConfig">类型</typeparam>
|
||||||
|
public class XmlConfig<TConfig> : BaseConfig<TConfig> where TConfig : XmlConfig<TConfig>, new()
|
||||||
|
{
|
||||||
|
#region 加载
|
||||||
|
/// <summary>
|
||||||
|
/// 当前可执行文件路径,末尾包括\
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>结果</returns>
|
||||||
|
private static string CurrentDir()
|
||||||
|
{
|
||||||
|
return Environment.CurrentDirectory.DealPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>加载指定配置文件</summary>
|
||||||
|
/// <param name="filename">文件名</param>
|
||||||
|
/// <returns>结果</returns>
|
||||||
|
public override bool Load(string filename)
|
||||||
|
{
|
||||||
|
if (filename.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
filename = CurrentDir() + ConfigFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filename.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
throw new ApplicationException($"未指定{typeof(TConfig).Name}的配置文件路径!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!File.Exists(filename))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
ConcurrentDictionary<string, Ident> idents = ConfigHelper.InitIdents(current);
|
||||||
|
|
||||||
|
XmlDocument doc = new XmlDocument();
|
||||||
|
doc.Load(filename);
|
||||||
|
XmlElement root = doc.DocumentElement; //获取根节点
|
||||||
|
foreach (Ident ident in idents.Values)
|
||||||
|
{
|
||||||
|
if (root != null)
|
||||||
|
{
|
||||||
|
var elements = root.GetElementsByTagName(ident.Key);
|
||||||
|
if (elements.Count == 1)
|
||||||
|
{
|
||||||
|
if (ident.IsList)
|
||||||
|
{
|
||||||
|
ident.Values.Clear();
|
||||||
|
foreach (XmlNode node in elements[0].ChildNodes)
|
||||||
|
{
|
||||||
|
ident.Values.Add(node.InnerText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ident.Value = elements[0].InnerText;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigHelper.LoadConfigValue(current, idents);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine(ex.Message);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>保存到配置文件中去</summary>
|
||||||
|
/// <param name="filename">文件名</param>
|
||||||
|
public override void Save(string filename)
|
||||||
|
{
|
||||||
|
if (filename.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
filename = CurrentDir() + ConfigFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (filename.IsNullOrWhiteSpace())
|
||||||
|
{
|
||||||
|
throw new ApplicationException($"未指定{typeof(TConfig).Name}的配置文件路径!");
|
||||||
|
}
|
||||||
|
|
||||||
|
ConcurrentDictionary<string, Ident> idents = ConfigHelper.InitIdents(current);
|
||||||
|
ConfigHelper.SaveConfigValue(Current, idents);
|
||||||
|
|
||||||
|
List<string> strs = new List<string> { "<?xml version=" + "\"" + "1.0" + "\"" + " encoding=" + "\"" + "utf-8" + "\"" + "?> ", "<!--" + Description + "--> " };
|
||||||
|
|
||||||
|
strs.Add("<" + GetType().Name + ">");
|
||||||
|
|
||||||
|
SortedList<int, Ident> slist = new SortedList<int, Ident>();
|
||||||
|
foreach (var ident in idents.Values)
|
||||||
|
{
|
||||||
|
slist.Add(ident.Index, ident);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var ident in slist.Values)
|
||||||
|
{
|
||||||
|
if (!ident.Description.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
strs.Add(" <!--" + ident.Description + "-->");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ident.IsList)
|
||||||
|
{
|
||||||
|
strs.Add(" <" + ident.Key + ">" + ident.Value + "</" + ident.Key + ">");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
strs.Add(" <" + ident.Key + ">");
|
||||||
|
foreach (string value in ident.Values)
|
||||||
|
{
|
||||||
|
strs.Add(" <Value>" + value + "</Value>");
|
||||||
|
}
|
||||||
|
|
||||||
|
strs.Add(" </" + ident.Key + ">");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
strs.Add("</" + GetType().Name + ">");
|
||||||
|
File.WriteAllLines(filename, strs.ToArray(), Encoding.UTF8);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion 加载
|
||||||
|
}
|
||||||
|
}
|
@ -22,7 +22,6 @@
|
|||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
using Sunny.UI.Properties;
|
|
||||||
|
|
||||||
namespace Sunny.UI
|
namespace Sunny.UI
|
||||||
{
|
{
|
||||||
@ -45,7 +44,7 @@ namespace Sunny.UI
|
|||||||
Custom,
|
Custom,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The GPS
|
/// The Gps
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Gps,
|
Gps,
|
||||||
|
|
||||||
@ -133,14 +132,14 @@ namespace Sunny.UI
|
|||||||
|
|
||||||
if (value == TMeterType.Gps)
|
if (value == TMeterType.Gps)
|
||||||
{
|
{
|
||||||
BackgroundImage = Resources.gps1;
|
BackgroundImage = Sunny.UI.Properties.Resources.gps1;
|
||||||
AngleImage = Resources.gps_postion;
|
AngleImage = Sunny.UI.Properties.Resources.gps_postion;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (value == TMeterType.Wind)
|
if (value == TMeterType.Wind)
|
||||||
{
|
{
|
||||||
BackgroundImage = Resources.wind;
|
BackgroundImage = Sunny.UI.Properties.Resources.wind;
|
||||||
AngleImage = Resources.wind_postion;
|
AngleImage = Sunny.UI.Properties.Resources.wind_postion;
|
||||||
}
|
}
|
||||||
|
|
||||||
Invalidate();
|
Invalidate();
|
||||||
|
@ -97,10 +97,39 @@ namespace Sunny.UI
|
|||||||
{
|
{
|
||||||
base.OnPaintFill(g, path);
|
base.OnPaintFill(g, path);
|
||||||
|
|
||||||
using var bmp = CreateImage(RandomEx.RandomChars(CodeLength));
|
using var bmp = CreateImage(RandomChars(CodeLength));
|
||||||
g.DrawImage(bmp, Width / 2 - bmp.Width / 2, 1);
|
g.DrawImage(bmp, Width / 2 - bmp.Width / 2, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private const string CHARS_62 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 生成字母和数字的随机字符串
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="length">长度</param>
|
||||||
|
/// <returns>结果</returns>
|
||||||
|
private static string RandomChars(int length = 10)
|
||||||
|
{
|
||||||
|
return RandomBase(CHARS_62.ToCharArray(), length);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string RandomBase(char[] pattern, int length)
|
||||||
|
{
|
||||||
|
if (pattern.IsNullOrEmpty())
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException();
|
||||||
|
}
|
||||||
|
|
||||||
|
string result = "";
|
||||||
|
for (int i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
Random random = new Random(DateTime.Now.Millisecond);
|
||||||
|
result += pattern[random.Next(0, pattern.Length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 绘制前景颜色
|
/// 绘制前景颜色
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -20,7 +20,6 @@
|
|||||||
* 2023-04-19: V3.3.5 增加可选择显示时激活的控件
|
* 2023-04-19: V3.3.5 增加可选择显示时激活的控件
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
using Sunny.UI.Properties;
|
|
||||||
using System;
|
using System;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
|
|
||||||
@ -96,12 +95,12 @@ namespace Sunny.UI
|
|||||||
{
|
{
|
||||||
loginImage = value;
|
loginImage = value;
|
||||||
|
|
||||||
if (loginImage == UILoginImage.Login1) BackgroundImage = Resources.Login1;
|
if (loginImage == UILoginImage.Login1) BackgroundImage = Sunny.UI.Properties.Resources.Login1;
|
||||||
if (loginImage == UILoginImage.Login2) BackgroundImage = Resources.Login2;
|
if (loginImage == UILoginImage.Login2) BackgroundImage = Sunny.UI.Properties.Resources.Login2;
|
||||||
if (loginImage == UILoginImage.Login3) BackgroundImage = Resources.Login3;
|
if (loginImage == UILoginImage.Login3) BackgroundImage = Sunny.UI.Properties.Resources.Login3;
|
||||||
if (loginImage == UILoginImage.Login4) BackgroundImage = Resources.Login4;
|
if (loginImage == UILoginImage.Login4) BackgroundImage = Sunny.UI.Properties.Resources.Login4;
|
||||||
if (loginImage == UILoginImage.Login5) BackgroundImage = Resources.Login5;
|
if (loginImage == UILoginImage.Login5) BackgroundImage = Sunny.UI.Properties.Resources.Login5;
|
||||||
if (loginImage == UILoginImage.Login6) BackgroundImage = Resources.Login6;
|
if (loginImage == UILoginImage.Login6) BackgroundImage = Sunny.UI.Properties.Resources.Login6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
* 2020-01-01: V2.2.0 增加文件说明
|
* 2020-01-01: V2.2.0 增加文件说明
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
|
using System.ComponentModel;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
|
|
||||||
namespace Sunny.UI
|
namespace Sunny.UI
|
||||||
@ -31,19 +32,19 @@ namespace Sunny.UI
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 自定义
|
/// 自定义
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DisplayText("Custom")]
|
[Description("Custom")]
|
||||||
Custom,
|
Custom,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 黑
|
/// 黑
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DisplayText("Black")]
|
[Description("Black")]
|
||||||
Black,
|
Black,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 白
|
/// 白
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DisplayText("White")]
|
[Description("White")]
|
||||||
White
|
White
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +60,7 @@ namespace Sunny.UI
|
|||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return Style.DisplayText();
|
return Style.Description();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@
|
|||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
using System.Drawing;
|
using System.Drawing;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
@ -55,85 +56,85 @@ namespace Sunny.UI
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 继承的全局主题
|
/// 继承的全局主题
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DisplayText("继承的全局主题")]
|
[Description("继承的全局主题")]
|
||||||
Inherited = -1,
|
Inherited = -1,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 自定义
|
/// 自定义
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DisplayText("Custom")]
|
[Description("Custom")]
|
||||||
Custom = 0,
|
Custom = 0,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 蓝
|
/// 蓝
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DisplayText("Blue")]
|
[Description("Blue")]
|
||||||
Blue = 1,
|
Blue = 1,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 绿
|
/// 绿
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DisplayText("Green")]
|
[Description("Green")]
|
||||||
Green = 2,
|
Green = 2,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 橙
|
/// 橙
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DisplayText("Orange")]
|
[Description("Orange")]
|
||||||
Orange = 3,
|
Orange = 3,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 红
|
/// 红
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DisplayText("Red")]
|
[Description("Red")]
|
||||||
Red = 4,
|
Red = 4,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 灰
|
/// 灰
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DisplayText("Gray")]
|
[Description("Gray")]
|
||||||
Gray = 5,
|
Gray = 5,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 紫
|
/// 紫
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DisplayText("Purple")]
|
[Description("Purple")]
|
||||||
Purple = 6,
|
Purple = 6,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// LayuiGreen
|
/// LayuiGreen
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DisplayText("LayuiGreen")]
|
[Description("LayuiGreen")]
|
||||||
LayuiGreen = 7,
|
LayuiGreen = 7,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// LayuiRed
|
/// LayuiRed
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DisplayText("LayuiRed")]
|
[Description("LayuiRed")]
|
||||||
LayuiRed = 8,
|
LayuiRed = 8,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// LayuiOrange
|
/// LayuiOrange
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DisplayText("LayuiOrange")]
|
[Description("LayuiOrange")]
|
||||||
LayuiOrange = 9,
|
LayuiOrange = 9,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 深蓝
|
/// 深蓝
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DisplayText("DarkBlue")]
|
[Description("DarkBlue")]
|
||||||
DarkBlue = 101,
|
DarkBlue = 101,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 黑
|
/// 黑
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DisplayText("Black")]
|
[Description("Black")]
|
||||||
Black = 102,
|
Black = 102,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 多彩的
|
/// 多彩的
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DisplayText("Colorful")]
|
[Description("Colorful")]
|
||||||
Colorful = 999
|
Colorful = 999
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -419,7 +419,7 @@ namespace Sunny.UI
|
|||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return Name.DisplayText();
|
return Name.Description();
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual bool BuiltIn => true;
|
public virtual bool BuiltIn => true;
|
||||||
|
@ -210,10 +210,11 @@ namespace Sunny.UI
|
|||||||
|
|
||||||
string thisFullName = form.GetType().FullName;
|
string thisFullName = form.GetType().FullName;
|
||||||
string section = "Info";
|
string section = "Info";
|
||||||
string inifile = Dir.CurrentDir() + "Language\\" + thisFullName + ".ini";
|
string fullName = Dir.CurrentDir() + "Language\\" + thisFullName + ".ini";
|
||||||
if (!File.Exists(inifile)) return;
|
if (!File.Exists(fullName)) return;
|
||||||
IniFile ini = new IniFile(Dir.CurrentDir() + "Language\\" + thisFullName + ".ini", System.Text.Encoding.UTF8);
|
IniFile ini = new IniFile(Dir.CurrentDir() + "Language\\" + thisFullName + ".ini", System.Text.Encoding.UTF8);
|
||||||
int count = ini.ReadInt("Controls", "Count", 0);
|
string readString = ini.ReadString("Controls", "Count", "");
|
||||||
|
if (!int.TryParse(readString, out int count)) return;
|
||||||
if (count == 0) return;
|
if (count == 0) return;
|
||||||
|
|
||||||
string key = UIStyles.CultureInfo.LCID.ToString() + ".Name";
|
string key = UIStyles.CultureInfo.LCID.ToString() + ".Name";
|
||||||
|
@ -72,7 +72,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="SunnyUI.Common" Version="3.8.2" />
|
<PackageReference Include="SunnyUI.Common" Version="3.8.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user