();
91 | var propInstance = _resolveWithParams(prop.PropertyType, false, attr?.Name ?? name);
92 | prop.SetValue(instance, propInstance);
93 | }
94 | }
95 | }
96 |
97 | }
98 |
--------------------------------------------------------------------------------
/IOCCodeGenerator/IOCCodeGenerator.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | bin\$(Configuration)\
6 | netstandard2.0
7 | preview
8 | true
9 | true
10 | UPPERIOC.Generators
11 | true
12 | enable
13 | true
14 | true
15 | true
16 |
17 | $(DefineConstants);ROSLYN_4
18 |
19 |
20 |
21 | True
22 | latest
23 | True
24 | MIT
25 |
26 | True
27 | latest
28 | True
29 | MIT
30 | zh-Hans
31 | True
32 | UPPERIOC的生成器组件
33 |
34 | True
35 |
36 |
37 | true
38 | true
39 | IOCG
40 | 1.0.0.21
41 | IOCG
42 | www
43 | True
44 | snupkg
45 | UPPERIOC.png
46 | README.md
47 | git
48 | Wwwwww
49 | True
50 | zh
51 | https://github.com/mrwangshipei/UPPERIOC
52 | https://github.com/mrwangshipei/UPPERIOC
53 | iocg
54 | 发布版本
55 | 1.0.0.1
56 | IOCCodeGenerator
57 | netstandard2.0
58 | C:\Program Files (x86)\Microsoft SDKs\NuGetPackages
59 | OnOutputUpdated
60 |
61 |
62 |
63 |
64 | False
65 |
66 |
67 |
68 |
69 |
70 | True
71 | \
72 |
73 |
74 | True
75 | \
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # UPPERIOC
2 |
3 | UPPERIOC 是一款专为 **WinForms** 和 **WPF** 上位机项目设计的轻量级 **IOC**(控制反转)插件系统,旨在简化模块化设计,提升系统解耦度,支持依赖注入、插件动态加载、事件总线等功能,适用于工业控制、数据采集、设备通信等领域。
4 |
5 | ---
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | ---
20 |
21 | ## 目录
22 |
23 | - [项目简介](#项目简介)
24 | - [功能亮点](#功能亮点)
25 | - [快速开始](#快速开始)
26 | - [系统架构](#系统架构)
27 | - [插件开发](#插件开发)
28 | - [示例项目](#示例项目)
29 | - [常见问题](#常见问题)
30 | - [许可证](#许可证)
31 |
32 | ## 项目简介
33 |
34 | UPPERIOC 旨在通过依赖注入、插件扩展等机制,使得上位机系统的模块化开发更加高效和灵活。通过实现 **插件化** 架构,你可以动态加载、卸载和更新系统中的功能模块,而无需修改主程序代码,从而提高系统的可维护性和扩展性。
35 |
36 | ## 功能亮点
37 |
38 | - **IOC 容器**:自动管理对象的生命周期和依赖关系,实现模块之间的解耦。
39 | - **插件系统**:支持动态加载和卸载插件,模块功能可以按需扩展。
40 | - **事件总线**:模块之间的通信通过事件机制实现,不直接依赖。
41 | - **注入机制**:支持通过属性注入和构造函数注入依赖对象。
42 |
43 | ## 快速开始
44 |
45 | ### 安装
46 |
47 | 首先,您需要通过 NuGet 安装 UPPERIOC:
48 |
49 | ```bash
50 | dotnet add package UPPERIOC
51 | ```
52 |
53 | ### 基本用法
54 |
55 | 0. **容器的初始化:**
56 |
57 | 在上位机的Program.cs,窗体打开之前使用如下代码初始化:
58 | ```csharp
59 | UpperIocApplication.RunInstance(md=>{});
60 | ```
61 |
62 | 1. **注册依赖:**
63 |
64 | ```csharp
65 | U.C.Register();
66 | // or
67 | MainForm m = new();
68 | U.C.Register(m);
69 | ```
70 |
71 | 2. **注入依赖:**
72 |
73 | ```csharp
74 | var f = U.C.GetInstance();
75 | public class MainForm
76 | {
77 | [IOCProperties]
78 | public IMyService MyService { get; set; }
79 |
80 | public MainForm()
81 | {
82 | // 使用 MyService
83 | }
84 | }
85 | ```
86 |
87 | 3. **插件加载:**
88 |
89 | ```csharp
90 | UpperIocApplication.RunInstance(md=>{
91 | md.AddModule();
92 | });
93 | ```
94 |
95 | 4. **发布事件:**
96 |
97 | ```csharp
98 | U.E.Publish();
99 | ```
100 |
101 | ## 系统架构
102 |
103 | 系统架构通过 **IOC 容器**、**插件加载器** 和 **事件总线** 实现解耦。各模块之间的交互通过注入和事件驱动进行。
104 |
105 | ### 架构图
106 |
107 | ```plaintext
108 |
109 | ## 1. 事件系统加载
110 | - 加载事件系统
111 | - 推送事件 "事件加载成功"
112 |
113 | ## 2. 日志中心加载
114 | - 加载日志中心
115 | - 推送事件 "日志中心加载成功"
116 |
117 | ## 3. IOC 和插件生命周期混合加载
118 | - 初始化 IOC 容器
119 | - 插件加载开始
120 | - 插件初始化
121 | - 插件生命周期事件推送
122 | - IOC 生命周期事件推送
123 |
124 | ## 4. 生命周期事件推送
125 | - 推送插件初始化成功事件
126 | - 推送 IOC 容器初始化成功事件
127 |
128 | ## 5. 注册软件退出事件
129 | - 注册容器注销前事件
130 | - 注册容器注销后事件
131 |
132 | ## 6. 退出操作
133 | - 容器注销
134 | - 触发 "容器注销前" 事件
135 | - 触发 "容器注销后" 事件
136 | ```
137 |
138 | ### 关键模块
139 |
140 | - **IOC 容器**:负责管理服务的注册与注入。
141 | - **插件系统**:动态加载、卸载插件。
142 | - **事件总线**:实现松散耦合。
143 |
144 | ## 插件开发
145 |
146 | UPPERIOC 提供了简洁的插件开发接口,帮助你快速构建可插拔的功能模块。
147 |
148 | ### 插件基本模板
149 |
150 | 每个插件需要实现 `IUPPERModule` 接口:
151 |
152 | ```csharp
153 | public class MyPlugin : IUPPERModule
154 | {
155 |
156 | }
157 | ```
158 | 可以通过实现生命周期接口来注册生命周期
159 |
160 | ## 示例项目
161 |
162 | 你可以参考以下示例项目来快速上手:
163 |
164 | - **WinForms 插件示例**: [还未完成](./examples/WinformDemo/README.md)
165 | - **WPF 插件示例**: [还未完成](./examples/WpfDemo/README.md)
166 |
167 | ## 常见问题
168 |
169 | ### 1. 如何定义插件间的依赖?
170 |
171 | 可以通过 IOC 容器管理插件之间的依赖关系,确保插件按正确顺序加载。
172 |
173 | ### 2. 是否支持跨项目使用?
174 |
175 | 是的,你可以将 UPPERIOC 作为一个共享库引入到多个项目中。
176 |
177 | ## 许可证
178 |
179 | 该项目使用 [MIT 许可证](./LICENSE)。
180 |
--------------------------------------------------------------------------------
/UPPERIOC/UPPER/Moudle_/ModuleConfiguaion.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.ComponentModel;
4 | using System.Linq;
5 | using System.Security.Permissions;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 | using UPPERIOC.UPPER.Event.AppEvent;
9 | using UPPERIOC.UPPER.Event.AppEvent.Impl;
10 | using UPPERIOC.UPPER.IOC.Center.IProvider;
11 | using UPPERIOC.UPPER.IOC.DefaultProvider;
12 | using UPPERIOC.UPPER.MainApplication.Log_;
13 | using UPPERIOC.UPPER.Moudle_;
14 |
15 |
16 | namespace UPPERIOC.UPPER.IOC.Center.Configuation
17 | {
18 | public class ModuleConfiguaion
19 | {
20 | private List _modules = new();
21 | private readonly List _logs = new();
22 | private IContainerProvider _containerProvider;
23 | private readonly object _lock = new();
24 | private ModuleLoader loader;
25 | public ApplicationEventManager EventManager { get; private set; }
26 |
27 | public List Modules
28 | {
29 | get
30 | {
31 | loader = new ModuleLoader(_modules);
32 | _modules = loader.GetLoadOrder();
33 | return _modules;
34 | }
35 | }
36 | public List UnLoadModules
37 | {
38 | get
39 | {
40 | loader = new ModuleLoader(_modules);
41 | _modules = loader.GetUnloadOrder();
42 | return _modules;
43 | }
44 | }
45 | public IReadOnlyList Logs => _logs;
46 |
47 | public IContainerProvider Provider
48 | {
49 | get
50 | {
51 | if (_containerProvider == null)
52 | {
53 | lock (_lock)
54 | {
55 | if (_containerProvider == null)
56 | {
57 | _containerProvider = new UPPERDefaultProvider();
58 |
59 | EventManager = _containerProvider.Rigister(new ApplicationEventManager()) as ApplicationEventManager;
60 | }
61 | }
62 | }
63 | return _containerProvider;
64 | }
65 | set
66 | {
67 | lock (_lock)
68 | {
69 | _containerProvider = value;
70 | EventManager = _containerProvider.Rigister(new ApplicationEventManager()) as ApplicationEventManager;
71 | }
72 | }
73 | }
74 |
75 | public void SetProvider() where T : IContainerProvider, new()
76 | {
77 | if (_containerProvider != null)
78 | {
79 | throw new Exception("SetProvider()函数必须在配置中置顶");
80 | }
81 | Provider = new T();
82 | }
83 |
84 | public void AddModule() where T : IUPPERModule, new()
85 | {
86 | _modules.Add(new T());
87 | }
88 |
89 | public void AddModule(IUPPERModule module)
90 | {
91 | if (module != null) _modules.Add(module);
92 | }
93 |
94 | public void AddLogger() where T : ILog, new()
95 | {
96 | _logs.Add(new T());
97 | }
98 |
99 | public void AddLogger(ILog log)
100 | {
101 | if (log != null) _logs.Add(log);
102 | }
103 |
104 | public static ModuleConfiguaion Configure(Action config)
105 | {
106 | var cfg = new ModuleConfiguaion();
107 | config(cfg);
108 | return cfg;
109 | }
110 | }
111 |
112 | }
113 |
--------------------------------------------------------------------------------
/TestDemo/ModuleTests.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Diagnostics;
4 | using System.IO;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 | using UPPER.Test.ApplicationEventTests;
9 | using UPPERIOC;
10 | using UPPERIOC.UPPER.IOC.Center.Interface;
11 | using UPPERTest.Util;
12 | using Xunit;
13 |
14 | namespace UPPERTest
15 | {
16 | namespace Sub {
17 | public class ModuleA : IUPPERModule
18 | {
19 | public override Type[] Dependencies => new Type[]
20 | {
21 | typeof(ModuleB)
22 | };
23 | }
24 |
25 | public class ModuleB : IUPPERModule
26 | {
27 | public override Type[] Dependencies => new Type[]
28 | {
29 | typeof(ModuleC)
30 | };
31 | }
32 |
33 | public class ModuleC : IUPPERModule
34 | {
35 | public override Type[] Dependencies => new Type[]
36 | {
37 | typeof(ModuleA)
38 | };
39 | }
40 | public class ModuleTests {
41 | [Fact]
42 | public void TestModuleLifecycle()
43 | {
44 | FileTempFile f = new FileTempFile();
45 | var assemblyPath = typeof(ProgramML).Assembly.Location;
46 | assemblyPath = assemblyPath.Replace(".dll", ".exe");
47 | //传入f._tempFile到程序中应该如何传;
48 | var process = Process.Start(new ProcessStartInfo
49 | {
50 | FileName = assemblyPath,
51 | Arguments = $"\"{f._tempFile}\"",
52 | RedirectStandardOutput = true,
53 | UseShellExecute = false,
54 | CreateNoWindow = true
55 | });
56 |
57 | process.WaitForExit();
58 |
59 | Assert.True(File.Exists(f._tempFile), "ProcessExit 未触发或未生成文件");
60 | Assert.Equal(File.ReadAllText(f._tempFile), "ok");
61 | }
62 | [Fact]
63 | public void DetectsTripleCircularDependency()
64 | {
65 | string exm = "";
66 | try
67 | {
68 | UPPERIOCApplication.RunInstance(md => {
69 | md.AddModule();
70 | md.AddModule();
71 | md.AddModule();
72 | });
73 | }
74 | catch (Exception ex)
75 | {
76 | exm = ex.Message;
77 | }
78 | Assert.Contains("存在循环依赖", exm);
79 | }
80 | }
81 | }
82 | public class ModuleTests
83 | {
84 | public class ModuleA : IUPPERModule
85 | {
86 | public override Type[] Dependencies => new Type[]
87 | {
88 | typeof(ModuleB)
89 | };
90 | }
91 |
92 | public class ModuleB : IUPPERModule
93 | {
94 | public override Type[] Dependencies => new Type[]
95 | {
96 | typeof(ModuleA)
97 | };
98 | }
99 |
100 | [Fact]
101 | public void DetectsCircularDependency() {
102 | string exm = "";
103 | try
104 | {
105 | UPPERIOCApplication.RunInstance(md => {
106 | md.AddModule();
107 | md.AddModule();
108 | });
109 | }
110 | catch (Exception ex)
111 | {
112 | exm = ex.Message;
113 | }
114 | Assert.Contains("存在循环依赖", exm);
115 | }
116 |
117 | }
118 | }
119 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Upperioc Code of Conduct
2 |
3 | Like the technical community as a whole, the Upperioc team and community is made up of a mixture of professionals and volunteers from all over the world, working on every aspect of the mission - including mentorship, teaching, and connecting people.
4 |
5 | Diversity is one of our huge strengths, but it can also lead to communication issues and unhappiness. To that end, we have a few ground rules that we ask people to adhere to. This code applies equally to founders, mentors and those seeking help and guidance.
6 |
7 | This isn’t an exhaustive list of things that you can’t do. Rather, take it in the spirit in which it’s intended - a guide to make it easier to enrich all of us and the technical communities in which we participate.
8 |
9 | This code of conduct applies to all spaces managed by the Upperioc project or ZhaoCai. This includes IRC, the mailing lists, the issue tracker, DSF events, and any other forums created by the project team which the community uses for communication. In addition, violations of this code outside these spaces may affect a person's ability to participate within them.
10 |
11 | If you believe someone is violating the code of conduct, we ask that you report it by emailing [wsp001112@gmail.com](mailto:wsp001112@gmail.com). For more details please see our
12 |
13 | - **Be friendly and patient.**
14 | - **Be welcoming.** We strive to be a community that welcomes and supports people of all backgrounds and identities. This includes, but is not limited to members of any race, ethnicity, culture, national origin, colour, immigration status, social and economic class, educational level, sex, sexual orientation, gender identity and expression, age, size, family status, political belief, religion, and mental and physical ability.
15 | - **Be considerate.** Your work will be used by other people, and you in turn will depend on the work of others. Any decision you take will affect users and colleagues, and you should take those consequences into account when making decisions. Remember that we're a world-wide community, so you might not be communicating in someone else's primary language.
16 | - **Be respectful.** Not all of us will agree all the time, but disagreement is no excuse for poor behavior and poor manners. We might all experience some frustration now and then, but we cannot allow that frustration to turn into a personal attack. It’s important to remember that a community where people feel uncomfortable or threatened is not a productive one. Members of the Upperioc community should be respectful when dealing with other members as well as with people outside the Upperioc community.
17 | - **Be careful in the words that you choose.** We are a community of professionals, and we conduct ourselves professionally. Be kind to others. Do not insult or put down other participants. Harassment and other exclusionary behavior aren't acceptable. This includes, but is not limited to:
18 | - Violent threats or language directed against another person.
19 | - Discriminatory jokes and language.
20 | - Posting sexually explicit or violent material.
21 | - Posting (or threatening to post) other people's personally identifying information ("doxing").
22 | - Personal insults, especially those using racist or sexist terms.
23 | - Unwelcome sexual attention.
24 | - Advocating for, or encouraging, any of the above behavior.
25 | - Repeated harassment of others. In general, if someone asks you to stop, then stop.
26 | - **When we disagree, try to understand why.** Disagreements, both social and technical, happen all the time and Upperioc is no exception. It is important that we resolve disagreements and differing views constructively. Remember that we’re different. The strength of Upperioc comes from its varied community, people from a wide range of backgrounds. Different people have different perspectives on issues. Being unable to understand why someone holds a viewpoint doesn’t mean that they’re wrong. Don’t forget that it is human to err and blaming each other doesn’t get us anywhere. Instead, focus on helping to resolve issues and learning from mistakes.
27 |
28 | Original text courtesy of the [Speak Up! project](http://web.archive.org/web/20141109123859/http://speakup.io/coc.html).
29 |
30 | ## Questions?
31 |
32 | If you have questions, please see . If that doesn't answer your questions, feel free to [contact us](mailto:wsp001112@gmail.com).
33 |
--------------------------------------------------------------------------------
/UPPERIOC/UPPER.Translate/Center/TranslateCenter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using System.ComponentModel;
5 | using System.Drawing;
6 | using System.Globalization;
7 | using System.Linq;
8 | using System.Security.Principal;
9 | using System.Text;
10 | using System.Threading.Tasks;
11 | using System.Windows.Forms;
12 | using UPPERIOC.UPPER.IOC.Center.IProvider;
13 | using UPPERIOC2.UPPER.Translate.Model;
14 | using UPPERIOC2.UPPER.UFileModel.Center;
15 | using UPPERIOC2.UPPER.Util;
16 | using static System.Net.Mime.MediaTypeNames;
17 |
18 | namespace UPPERIOC2.UPPER.Translate.Center
19 | {
20 | public class TranslateCenter
21 | {
22 | public static TranslateCenter Instance { get; set; } = new TranslateCenter();
23 | internal TranslateModel TranslateModel;
24 | internal Translateblock TranslateBlock;
25 | internal IContainerProvider ipd;
26 | internal string L;
27 | List root = new List(25);
28 | List Ignore= new List(25);
29 | internal TranslateCenter(IContainerProvider ipd) {
30 |
31 | this.ipd = ipd;
32 | }
33 | internal TranslateCenter()
34 | {
35 |
36 | }
37 | public void SetRootWindows(Component com) {
38 | if (ipd == null)
39 | {
40 | return;
41 | }
42 | if (com is MenuStrip mt) {
43 | foreach (Component c in mt.Items) {
44 |
45 | SetRootWindows(c);
46 | }
47 | mt.Text = GetText(mt.Text);
48 |
49 | }
50 | else if (com is ToolStrip it)
51 | {
52 | foreach (ToolStripItem item in it.Items)
53 | {
54 | SetRootWindows(item);
55 | }
56 | it.Text = GetText(it.Text);
57 |
58 | }else if (com is ToolStripItem ita)
59 | {
60 | ita.Text = GetText(ita.Text);
61 |
62 | }
63 | else if (com is Control con)
64 | {
65 | foreach (Control item in con.Controls)
66 | {
67 | SetRootWindows(item);
68 | }
69 | con.Text = GetText(con.Text);
70 | }
71 |
72 | /* con.ControlAdded -= SetControlAdd;
73 | con.ControlAdded += SetControlAdd;
74 | con.TextChanged -= SetTextChange;
75 | con.TextChanged += SetTextChange;*/
76 | }
77 | internal void SetLanguage(string lan)
78 | {
79 | L = lan;
80 | if (null == TranslateModel)
81 | {
82 | TranslateModel =F.I.GetModel(new TranslateModel());
83 | }
84 | if (null != TranslateModel)
85 | {
86 | TranslateBlock = TranslateModel.Translateblocks.Find(x=> x.Name == lan);
87 | if (TranslateBlock == null)
88 | {
89 | TranslateBlock = new Translateblock();
90 | TranslateBlock.Name = lan;
91 | TranslateModel.Translateblocks.Add(TranslateBlock);
92 | }
93 | }
94 | }
95 | public void SetIgnoreCon(Control con)
96 | {
97 | Ignore.Add(con);
98 | }
99 | private void SetControlAdd(object sender, ControlEventArgs e)
100 | {
101 |
102 | if (Ignore.Contains(e.Control))
103 | {
104 | return;
105 | }
106 | e.Control.ControlAdded -= SetControlAdd;
107 | e.Control.ControlAdded += SetControlAdd;
108 | if (!string.IsNullOrWhiteSpace(e.Control.Text))
109 | {
110 | e.Control.Text = GetText(e.Control.Text);
111 |
112 | }
113 |
114 | e.Control.TextChanged -= SetTextChange;
115 | e.Control.TextChanged += SetTextChange;
116 |
117 | }
118 |
119 | private void SetTextChange(object sender, EventArgs e)
120 | {
121 | Control con = sender as Control;
122 | if (!string.IsNullOrWhiteSpace(con.Text) && con.Text != GetText(con.Text))
123 | {
124 | con.TextChanged -= SetTextChange;
125 | con.Text = GetText(con.Text);
126 | con.TextChanged += SetTextChange;
127 | }
128 | }
129 |
130 | public string GetText(string text)
131 | {
132 | if (ipd == null)
133 | {
134 | return text;
135 | }
136 | if (string.IsNullOrWhiteSpace(text))
137 | {
138 | return text;
139 | }
140 |
141 | var str = TranslateBlock.Values.Find(x => x.Key == text && !string.IsNullOrWhiteSpace(x.Value)).Value;
142 | if (string.IsNullOrWhiteSpace(str))
143 | {
144 | str = TranslateUtil.Transcale(text);
145 | if (string.IsNullOrWhiteSpace(str))
146 | {
147 | str = text;
148 | }
149 | TranslateBlock.Values.Add(new KeyValue(text,str));
150 | F.I.SaveModel(TranslateModel);
151 | }
152 | if (string.IsNullOrWhiteSpace(str))
153 | {
154 | return text;
155 | }
156 | return str;
157 | }
158 | }
159 | }
160 |
--------------------------------------------------------------------------------
/UPPERIOC/Util/HashHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Management;
4 | using System.Security.Cryptography;
5 | using System.Text;
6 | using System.Windows.Forms;
7 | using System.Runtime.InteropServices;
8 | using UPPERIOC.UPPER;
9 | namespace UPPERIOC2.UPPER.Util
10 | {
11 | public class HashHelper
12 | {
13 | public static string EncryptWithSalt(string salt,string machineCode = "")
14 | {
15 | if (string.IsNullOrWhiteSpace(machineCode))
16 | {
17 | machineCode = GenerateMachineId();
18 |
19 | }
20 | using (var sha256 = SHA256.Create())
21 | {
22 | var saltedMachineCode = Encoding.UTF8.GetBytes($"{machineCode}{salt}");
23 | var hash = sha256.ComputeHash(saltedMachineCode);
24 |
25 | // 将哈希值转换为十六进制字符串
26 | var hashString = BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
27 |
28 | return hashString;
29 | }
30 | }
31 | internal static bool VerifyWithSalt(string salt, string storedHash)
32 | {
33 | //string machineCode = GenerateMachineId();
34 |
35 | var computedHash = EncryptWithSalt(salt);
36 | return computedHash == storedHash;
37 | }
38 | static string GenerateMachineId()
39 | {
40 | // 获取多个系统属性以生成唯一标识符
41 | string cpuId = GetCpuId();
42 | string biosId = GetBiosId();
43 | string baseBoardId = GetBaseBoardId();
44 |
45 | // 将所有属性合并成一个字符串
46 | string combinedId = $"{cpuId}{biosId}{baseBoardId}";
47 |
48 | // 使用SHA256哈希算法对合并后的字符串进行哈希处理
49 | using (SHA256 sha256Hash = SHA256.Create())
50 | {
51 | byte[] data = sha256Hash.ComputeHash(Encoding.UTF8.GetBytes(combinedId));
52 |
53 | // 将哈希值转换为十六进制字符串
54 | StringBuilder sBuilder = new StringBuilder();
55 |
56 | for (int i = 0; i < data.Length; i++)
57 | {
58 | sBuilder.Append(data[i].ToString("x2"));
59 | }
60 |
61 | return sBuilder.ToString();
62 | }
63 | }
64 | [ComVisible(true)]
65 | private static string GetCpuId()
66 | {
67 | string cpuInfo = string.Empty;
68 | try
69 | {
70 | string s = "SELECT ProcessorId FROM Win32_Processor";
71 | ManagementObjectSearcher searcher = new ManagementObjectSearcher(s);
72 |
73 | foreach (ManagementObject mo in searcher.Get())
74 | {
75 | cpuInfo = (string)mo["ProcessorId"];
76 | break; // 通常只需要第一个CPU的ID
77 | }
78 |
79 | }
80 | catch (ManagementException ex)
81 | {
82 | LogCenter.Log(UPPERIOC.UPPER.enums.LogType.Error,"WMI 查询失败!");
83 | LogCenter.Log(UPPERIOC.UPPER.enums.LogType.Error, "错误消息: " + ex.Message);
84 | LogCenter.Log(UPPERIOC.UPPER.enums.LogType.Error, "错误代码: " + ex.ErrorCode);
85 | if (ex.InnerException != null)
86 | {
87 | LogCenter.Log(UPPERIOC.UPPER.enums.LogType.Error, "内部异常: " + ex.InnerException.Message);
88 | }
89 | cpuInfo = "UnKnowCpuInfo";
90 |
91 | }
92 |
93 |
94 | return cpuInfo;
95 | }
96 | [ComVisible(true)]
97 |
98 | private static string GetBiosId()
99 | {
100 | string biosId = string.Empty;
101 |
102 | ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT SerialNumber,SMBIOSBIOSVersion FROM Win32_BIOS");
103 | try
104 | {
105 | foreach (ManagementObject mo in searcher.Get())
106 | {
107 | biosId = (string)mo["SerialNumber"];
108 | if (!string.IsNullOrEmpty(biosId)) break; // 如果SerialNumber为空,则尝试其他属性
109 | biosId = (string)mo["SMBIOSBIOSVersion"];
110 | break;
111 | }
112 |
113 | }
114 | catch (Exception)
115 | {
116 | biosId = "UnknowBiosId";
117 | }
118 |
119 | return biosId;
120 | }
121 | [ComVisible(true)]
122 |
123 | private static string GetBaseBoardId()
124 | {
125 | string baseBoardId = string.Empty;
126 | try
127 | {
128 | ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT SerialNumber FROM Win32_BaseBoard");
129 |
130 | foreach (ManagementObject mo in searcher.Get())
131 | {
132 | baseBoardId = (string)mo["SerialNumber"];
133 | if (!string.IsNullOrEmpty(baseBoardId)) break; // 如果SerialNumber为空,则可能没有其他合适的属性
134 | }
135 |
136 |
137 | }
138 | catch (Exception)
139 | {
140 | baseBoardId = "UnKnowBaseBoardIdid";
141 |
142 | }
143 | return baseBoardId;
144 | }
145 |
146 | internal static bool VerifyWithSalt(string solt, object value)
147 | {
148 | throw new NotImplementedException();
149 | }
150 | }
151 | }
152 |
--------------------------------------------------------------------------------
/UPPERIOC.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.9.34723.18
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UPPER.Test", "TestDemo\UPPER.Test.csproj", "{91BD652E-C624-4F1B-B500-C5816A440579}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IOCCodeGenerator", "IOCCodeGenerator\IOCCodeGenerator.csproj", "{58037466-8377-498F-BB03-CBA62AF571FC}"
9 | EndProject
10 | Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "UPPER.Shared", "UPPER.Shared\UPPER.Shared.shproj", "{CF82D5A3-E4E9-447B-8EB3-6200954CFE4E}"
11 | EndProject
12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UPPERIOC", "UPPERIOC\UPPERIOC.csproj", "{7BC98436-8116-4547-A174-9D0AC126A3CC}"
13 | EndProject
14 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Test", "Test", "{02EA681E-C7D8-13C7-8484-4AC65E1B71E8}"
15 | EndProject
16 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TestProgrem", "TestProgrem", "{2C8ECB36-0D14-46F1-9EAF-6B3C50E3E1D6}"
17 | EndProject
18 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UPPER.Test.ApplicationEventTests", "UPPER.Test.ApplicationEventTests\UPPER.Test.ApplicationEventTests.csproj", "{90875408-4071-413E-AEF7-D1607F03A6B0}"
19 | EndProject
20 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UPPER.Test.MoudleLifecycle", "UPPER.Test.MoudleLifecycle\UPPER.Test.MoudleLifecycle.csproj", "{D22F4CD3-7B98-4E4E-81DE-9A54C983D576}"
21 | EndProject
22 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UPPER.TestTests", "UPPER.TestTests\UPPER.TestTests.csproj", "{ABA2D77D-B97B-4F5A-BE05-E734420D3F9B}"
23 | EndProject
24 | Global
25 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
26 | Debug|Any CPU = Debug|Any CPU
27 | Release|Any CPU = Release|Any CPU
28 | EndGlobalSection
29 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
30 | {91BD652E-C624-4F1B-B500-C5816A440579}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
31 | {91BD652E-C624-4F1B-B500-C5816A440579}.Debug|Any CPU.Build.0 = Debug|Any CPU
32 | {91BD652E-C624-4F1B-B500-C5816A440579}.Release|Any CPU.ActiveCfg = Release|Any CPU
33 | {91BD652E-C624-4F1B-B500-C5816A440579}.Release|Any CPU.Build.0 = Release|Any CPU
34 | {58037466-8377-498F-BB03-CBA62AF571FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
35 | {58037466-8377-498F-BB03-CBA62AF571FC}.Debug|Any CPU.Build.0 = Debug|Any CPU
36 | {58037466-8377-498F-BB03-CBA62AF571FC}.Release|Any CPU.ActiveCfg = Release|Any CPU
37 | {58037466-8377-498F-BB03-CBA62AF571FC}.Release|Any CPU.Build.0 = Release|Any CPU
38 | {7BC98436-8116-4547-A174-9D0AC126A3CC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
39 | {7BC98436-8116-4547-A174-9D0AC126A3CC}.Debug|Any CPU.Build.0 = Debug|Any CPU
40 | {7BC98436-8116-4547-A174-9D0AC126A3CC}.Release|Any CPU.ActiveCfg = Release|Any CPU
41 | {7BC98436-8116-4547-A174-9D0AC126A3CC}.Release|Any CPU.Build.0 = Release|Any CPU
42 | {90875408-4071-413E-AEF7-D1607F03A6B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
43 | {90875408-4071-413E-AEF7-D1607F03A6B0}.Debug|Any CPU.Build.0 = Debug|Any CPU
44 | {90875408-4071-413E-AEF7-D1607F03A6B0}.Release|Any CPU.ActiveCfg = Release|Any CPU
45 | {90875408-4071-413E-AEF7-D1607F03A6B0}.Release|Any CPU.Build.0 = Release|Any CPU
46 | {D22F4CD3-7B98-4E4E-81DE-9A54C983D576}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
47 | {D22F4CD3-7B98-4E4E-81DE-9A54C983D576}.Debug|Any CPU.Build.0 = Debug|Any CPU
48 | {D22F4CD3-7B98-4E4E-81DE-9A54C983D576}.Release|Any CPU.ActiveCfg = Release|Any CPU
49 | {D22F4CD3-7B98-4E4E-81DE-9A54C983D576}.Release|Any CPU.Build.0 = Release|Any CPU
50 | {ABA2D77D-B97B-4F5A-BE05-E734420D3F9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
51 | {ABA2D77D-B97B-4F5A-BE05-E734420D3F9B}.Debug|Any CPU.Build.0 = Debug|Any CPU
52 | {ABA2D77D-B97B-4F5A-BE05-E734420D3F9B}.Release|Any CPU.ActiveCfg = Release|Any CPU
53 | {ABA2D77D-B97B-4F5A-BE05-E734420D3F9B}.Release|Any CPU.Build.0 = Release|Any CPU
54 | EndGlobalSection
55 | GlobalSection(SolutionProperties) = preSolution
56 | HideSolutionNode = FALSE
57 | EndGlobalSection
58 | GlobalSection(NestedProjects) = preSolution
59 | {91BD652E-C624-4F1B-B500-C5816A440579} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
60 | {2C8ECB36-0D14-46F1-9EAF-6B3C50E3E1D6} = {02EA681E-C7D8-13C7-8484-4AC65E1B71E8}
61 | {90875408-4071-413E-AEF7-D1607F03A6B0} = {2C8ECB36-0D14-46F1-9EAF-6B3C50E3E1D6}
62 | {D22F4CD3-7B98-4E4E-81DE-9A54C983D576} = {2C8ECB36-0D14-46F1-9EAF-6B3C50E3E1D6}
63 | EndGlobalSection
64 | GlobalSection(ExtensibilityGlobals) = postSolution
65 | SolutionGuid = {222FD9B0-85B4-43F1-B03B-A85920FDCC8F}
66 | EndGlobalSection
67 | GlobalSection(SharedMSBuildProjectFiles) = preSolution
68 | UPPER.Shared\UPPER.Shared.projitems*{58037466-8377-498f-bb03-cba62af571fc}*SharedItemsImports = 5
69 | UPPER.Shared\UPPER.Shared.projitems*{cf82d5a3-e4e9-447b-8eb3-6200954cfe4e}*SharedItemsImports = 13
70 | EndGlobalSection
71 | EndGlobal
72 |
--------------------------------------------------------------------------------
/UPPERIOC/UPPER.UFileModel/Entry/DirectoryEx.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Xml;
3 | using System.Xml.Schema;
4 | using System.Xml.Serialization;
5 |
6 | namespace Kernal
7 | {
8 | #region 可序列化字典类 + public class DictionaryEx
9 | ///
10 | /// 可序列化字典类
11 | ///
12 | /// 键泛型
13 | /// 值泛型
14 | [System.Serializable]
15 | public class DictionaryEx
16 | : Dictionary, IXmlSerializable
17 | {
18 | #region 构造函数
19 |
20 | #region 默认构造函数 + public DictionaryEx()
21 | ///
22 | /// 默认构造函数
23 | ///
24 | public DictionaryEx()
25 | : base()
26 | {
27 |
28 | }
29 | #endregion
30 |
31 | #region 构造函数 + public DictionaryEx(int capacity)
32 | ///
33 | /// 构造函数
34 | ///
35 | /// 可包含的初始元素数
36 | public DictionaryEx(int capacity)
37 | : base(capacity)
38 | {
39 |
40 | }
41 | #endregion
42 |
43 | #region 构造函数 + public DictionaryEx(IEqualityComparer comparer)
44 | ///
45 | /// 构造函数
46 | ///
47 | /// 比较键时要使用的 比较器 实现,或者为 null,以便为键类型使用默认的 比较器
48 | public DictionaryEx(IEqualityComparer comparer)
49 | : base(comparer)
50 | {
51 |
52 | }
53 | #endregion
54 |
55 | #region 构造函数 + public DictionaryEx(IDictionary dictionary)
56 | ///
57 | /// 构造函数
58 | ///
59 | /// 初始数据
60 | public DictionaryEx(IDictionary dictionary)
61 | : base(dictionary)
62 | {
63 |
64 | }
65 | #endregion
66 |
67 | #region 构造函数 + public DictionaryEx(int capacity, IEqualityComparer comparer)
68 | ///
69 | /// 构造函数
70 | ///
71 | /// 可包含的初始元素数
72 | /// 比较键时要使用的 比较器 实现,或者为 null,以便为键类型使用默认的 比较器
73 | public DictionaryEx(int capacity, IEqualityComparer comparer)
74 | : base(capacity, comparer)
75 | {
76 |
77 | }
78 | #endregion
79 |
80 | #region 构造函数 + public DictionaryEx(IDictionary dictionary, IEqualityComparer comparer)
81 | ///
82 | /// 构造函数
83 | ///
84 | /// 初始数据
85 | /// 比较键时要使用的 比较器 实现,或者为 null,以便为键类型使用默认的 比较器
86 | public DictionaryEx(IDictionary dictionary, IEqualityComparer comparer)
87 | : base(dictionary, comparer)
88 | {
89 |
90 | }
91 | #endregion
92 |
93 | #endregion
94 |
95 | #region 取得概要 + public XmlSchema GetSchema()
96 | ///
97 | /// 取得概要
98 | /// 注:根据MSDN的文档,此方法为保留方法,一定返回 null。
99 | ///
100 | /// Xml概要
101 | public XmlSchema GetSchema()
102 | {
103 | return null;
104 | }
105 | #endregion
106 |
107 | #region 从 XML 对象中反序列化生成本对象 + public void ReadXml(XmlReader reader)
108 | ///
109 | /// 从 XML 对象中反序列化生成本对象
110 | ///
111 | /// 包含反序列化对象的 XmlReader 流
112 | public void ReadXml(XmlReader reader)
113 | {
114 | XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
115 | XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));
116 | bool wasEmpty = reader.IsEmptyElement;
117 | reader.Read();
118 | if (wasEmpty) return;
119 |
120 | while (reader.NodeType != XmlNodeType.EndElement)
121 | {
122 | reader.ReadStartElement("Item");
123 | reader.ReadStartElement("Key");
124 | TKey key = (TKey)keySerializer.Deserialize(reader);
125 | reader.ReadEndElement();
126 | reader.ReadStartElement("Value");
127 | TValue value = (TValue)valueSerializer.Deserialize(reader);
128 | reader.ReadEndElement();
129 | this.Add(key, value);
130 | reader.ReadEndElement();
131 | reader.MoveToContent();
132 | }
133 |
134 | reader.ReadEndElement();
135 | }
136 | #endregion
137 |
138 | #region 将本对象序列化为 XML 对象 + public void WriteXml(XmlWriter writer)
139 | ///
140 | /// 将本对象序列化为 XML 对象
141 | ///
142 | /// 待写入的 XmlWriter 对象
143 | public void WriteXml(XmlWriter writer)
144 | {
145 | XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
146 | XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));
147 | foreach (TKey key in this.Keys)
148 | {
149 | writer.WriteStartElement("Item");
150 | writer.WriteStartElement("Key");
151 | keySerializer.Serialize(writer, key);
152 | writer.WriteEndElement();
153 | writer.WriteStartElement("Value");
154 | TValue value = this[key];
155 | valueSerializer.Serialize(writer, value);
156 | writer.WriteEndElement();
157 | writer.WriteEndElement();
158 | }
159 | }
160 | #endregion
161 | }
162 | #endregion
163 | }
--------------------------------------------------------------------------------
/UPPERIOC/UPPER/IOC/Moudle/UPPERIOCModule.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Reflection;
5 | using System.Runtime.InteropServices;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 | using UPPERIOC.UPPER.Event.AppEvent;
9 | using UPPERIOC.UPPER.Event.AppEvent.Impl;
10 | using UPPERIOC.UPPER.IOC.Annaiation;
11 | using UPPERIOC.UPPER.IOC.Center.IProvider;
12 | using UPPERIOC.UPPER.IOC.Extend;
13 | using UPPERIOC.UPPER.Moudle_;
14 | using UPPERIOC2.UPPER.UIOC.Center;
15 |
16 | namespace UPPERIOC.UPPER.IOC.Moudle
17 | {
18 | public class UPPERIOCModule : IUPPERModule, IModulePostConstruction, IModuleInitialization, IModulePostInitialization, IModulePreInitialization
19 | {
20 | ApplicationEventManager ma;
21 | IContainerProvider containerProvider;
22 |
23 | public override Type[] Dependencies { get; } = new Type[0];
24 |
25 |
26 | public void OnPostConstruct(IContainerProvider containerProvider)
27 | {
28 |
29 | }
30 |
31 | public void OnPreInitialize(IContainerProvider containerProvider)
32 | {
33 |
34 | }
35 |
36 | public void OnPostInitialize(IContainerProvider containerProvider)
37 | {
38 |
39 | }
40 | public void OnInitialize(IContainerProvider containerProvider)
41 | {
42 |
43 |
44 | this.containerProvider = containerProvider;
45 | U.C = containerProvider;
46 | try
47 | {
48 |
49 | var mainAssembly = GetAllReferencedAssemblies(Assembly.GetEntryAssembly())
50 | .FindAll(assembly => {
51 | try
52 | {
53 | return assembly.GetTypes().Any(type => type.Name == "IOCGeneratedRegistration");
54 |
55 | }
56 | catch (Exception ex )
57 | {
58 | return false;
59 | }
60 | }
61 | );
62 |
63 | if (mainAssembly != null)
64 | {
65 | foreach (var item in mainAssembly)
66 | {
67 | var type = item.GetType("UPPER.Generated.IOCGeneratedRegistration");
68 | var method = type?.GetMethod("RegisterAll", BindingFlags.Public | BindingFlags.Static);
69 | if (method != null)
70 | {
71 | try
72 | {
73 |
74 | method?.Invoke(null, new object[] { containerProvider }); // 调用静态方法
75 | Console.WriteLine("RegisterAll invoked successfully.");
76 | }
77 | catch (Exception ee)
78 | {
79 | LogCenter.Log(enums.LogType.Error,"RegisterAll Error:" + ee.Message + ee.StackTrace);
80 |
81 | Console.WriteLine("RegisterAll Error:" + ee.Message + ee.StackTrace);
82 | }
83 | }
84 |
85 | }
86 |
87 | }
88 | Console.WriteLine($"Error invoking Fail");
89 |
90 | }
91 | catch (Exception ex)
92 | {
93 | Console.WriteLine($"Error invoking RegisterAll: {ex}");
94 | }
95 | }
96 | public static List GetAllReferencedAssemblies(Assembly assembly)
97 | {
98 | var referencedAssemblies = new HashSet();
99 | var queue = new Queue();
100 | queue.Enqueue(assembly);
101 |
102 | while (queue.Count > 0)
103 | {
104 | var currentAssembly = queue.Dequeue();
105 | if (!referencedAssemblies.Contains(currentAssembly))
106 | {
107 | referencedAssemblies.Add(currentAssembly);
108 | foreach (var reference in currentAssembly.GetReferencedAssemblies())
109 | {
110 | try
111 | {
112 | var referencedAssembly = Assembly.Load(reference);
113 | if (!referencedAssemblies.Contains(referencedAssembly))
114 | {
115 | queue.Enqueue(referencedAssembly);
116 | }
117 | }
118 | catch (Exception ex)
119 | {
120 | // 忽略找不到的程序集
121 | }
122 | }
123 | }
124 | }
125 |
126 | return referencedAssemblies.ToList();
127 | }
128 |
129 |
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/UPPERIOC/Util/RegisterHelper.cs:
--------------------------------------------------------------------------------
1 | namespace UPPERIOC2.UPPER.Util
2 | {
3 | public class RegisterHelper
4 | {
5 | public static RegisterHelper Instance = new RegisterHelper();
6 |
7 | ///
8 | /// 允许用户将自定义实现替换默认的注册表/文件操作逻辑。
9 | ///
10 | public static void SetRegisterWriter(RegisterHelper instanc)
11 | {
12 | Instance = instanc;
13 | }
14 | public object _lockobj = new object();
15 | // 读取注册表值或文件值
16 | internal virtual string GetLockFile(string keyName, string valueName)
17 | {
18 | #if NET462
19 | // 在 .NET Framework 4.6.2 下使用注册表
20 | lock (_lockobj)
21 | return ReadFromRegistry(keyName, valueName);
22 | #else
23 | // 在 .NET Standard 2.0 下,根据平台判断使用注册表或文件存储
24 | if (IsWindows() && SupportsRegistry())
25 | {
26 | lock (_lockobj)
27 | return ReadFromRegistry(keyName, valueName);
28 | }
29 | else
30 | {
31 | lock (_lockobj)
32 | return ReadFromFile(keyName, valueName);
33 | }
34 | #endif
35 | }
36 |
37 | // 写入注册表值或文件值
38 | internal virtual void SaveLockFile(string keyName, string valueName, object value)
39 | {
40 | #if NET462
41 | // 在 .NET Framework 4.6.2 下使用注册表
42 | lock (_lockobj)
43 | WriteToRegistry(keyName, valueName, value);
44 | #else
45 | // 在 .NET Standard 2.0 下,根据平台判断使用注册表或文件存储
46 | if (IsWindows() && SupportsRegistry())
47 | {
48 | lock (_lockobj)
49 | WriteToRegistry(keyName, valueName, value);
50 | }
51 | else
52 | {
53 | lock (_lockobj)
54 | WriteToFile(keyName, valueName, value);
55 | }
56 | #endif
57 | }
58 |
59 | internal virtual void UnloadLockFile(string keyName, string valueName)
60 | {
61 | #if NET462
62 | // 在 .NET Framework 4.6.2 下使用注册表
63 | WriteToRegistry(keyName, valueName, "nothingisthere");
64 | #else
65 | // 在 .NET Standard 2.0 下,根据平台判断使用注册表或文件存储
66 | if (IsWindows() && SupportsRegistry())
67 | {
68 | lock (_lockobj)
69 | WriteToRegistry(keyName, valueName, "nothingisthere");
70 | }
71 | else
72 | {
73 | lock (_lockobj)
74 | WriteToFile(keyName, valueName, "nothingisthere");
75 | }
76 | #endif
77 | }
78 |
79 | private string ReadFromRegistry(string keyName, string valueName)
80 | {
81 | #if NET462 || (NETSTANDARD && WINDOWS && INCLUDE_REGISTRY)
82 |
83 | #endif
84 | using (var key = Microsoft.Win32.Registry.CurrentUser.OpenSubKey(keyName))
85 | {
86 | if (key != null)
87 | {
88 | var value = key.GetValue(valueName);
89 | if (value != null)
90 | {
91 | return value.ToString();
92 | }
93 | }
94 | }
95 | return null;
96 | }
97 |
98 | private void WriteToRegistry(string keyName, string valueName, object value)
99 | {
100 |
101 | using (var key = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(keyName))
102 | {
103 | key.SetValue(valueName, value);
104 | }
105 | }
106 |
107 | #if !NET462
108 | private string ReadFromFile(string keyName, string valueName)
109 | {
110 | string filePath = GetFilePath(keyName, valueName);
111 | if (System.IO.File.Exists(filePath))
112 | {
113 | return System.IO.File.ReadAllText(filePath);
114 | }
115 | return null;
116 | }
117 |
118 | private void WriteToFile(string keyName, string valueName, object value)
119 | {
120 | string filePath = GetFilePath(keyName, valueName);
121 | string directoryPath = System.IO.Path.GetDirectoryName(filePath);
122 | if (!System.IO.Directory.Exists(directoryPath))
123 | {
124 | System.IO.Directory.CreateDirectory(directoryPath);
125 | }
126 | System.IO.File.WriteAllText(filePath, value.ToString());
127 | }
128 |
129 | // 获取文件路径
130 | private string GetFilePath(string keyName, string valueName)
131 | {
132 | string baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
133 | return System.IO.Path.Combine(baseDirectory, keyName, $"{valueName}.txt");
134 | }
135 |
136 | // 判断是否是 Windows 平台
137 | private bool IsWindows()
138 | {
139 | return System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows);
140 | }
141 |
142 | // 判断是否支持注册表操作
143 | private bool SupportsRegistry()
144 | {
145 | return true;
146 | }
147 | #endif
148 | }
149 | }
150 |
--------------------------------------------------------------------------------
/UPPERIOC/Util/Extend/StaticExtend.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Concurrent;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Reflection;
6 | using UPPERIOC.UPPER.IOC.MyTypeInfo;
7 |
8 | namespace UPPERIOC.UPPER.IOC.Extend
9 | {
10 | public static class StaticExtend
11 | {
12 | // 判断是否有指定特性存在于基类上
13 | public static bool HasBaseClassWithAttribute(this Type type) where TAttribute : Attribute
14 | {
15 | while (type != null && type != typeof(object))
16 | {
17 | if (type.GetCustomAttribute() != null)
18 | return true;
19 |
20 | type = type.BaseType;
21 | }
22 | return false;
23 | }
24 |
25 | // 判断是否是单例(根据名称)
26 | public static bool? IsSingleBean(this ConcurrentDictionary dict, string typeName)
27 | {
28 | var entry = dict.FirstOrDefault(x => x.Key.TypeName == typeName);
29 | return entry.Key?.SingleBean;
30 | }
31 |
32 | // 判断是否是单例(根据类型)
33 | public static bool? IsSingleBean(this ConcurrentDictionary dict, Type type)
34 | {
35 | var entry = dict.FirstOrDefault(item => item.Key.Type.IsCompatibleWith(type));
36 | return entry.Key?.SingleBean;
37 | }
38 |
39 | // 查找第一个满足条件的键值对
40 | public static KeyValuePair? Find(this ConcurrentDictionary dict, Func, bool> predicate)
41 | {
42 | foreach (var item in dict)
43 | {
44 | if (predicate(item))
45 | return item;
46 | }
47 | return null;
48 | }
49 |
50 | // 获取所有符合类型的实例
51 | public static object[] GetAllInstances(this ConcurrentDictionary dict, Type type)
52 | {
53 | return dict
54 | .Where(item => item.Key.Type.IsCompatibleWith(type))
55 | .Select(item => item.Value)
56 | .ToArray();
57 | }
58 |
59 | // 获取实例(通过类型或名称)
60 | public static object GetInstance(this ConcurrentDictionary dict, Type type = null, string name = null, bool includeSub = false)
61 | {
62 | if (type != null)
63 | {
64 | return includeSub
65 | ? dict.FirstOrDefault(item => item.Key.Type.IsCompatibleWith(type)).Value
66 | : dict.FirstOrDefault(item => item.Key.Type == type).Value;
67 | }
68 |
69 | if (!string.IsNullOrEmpty(name))
70 | {
71 | return dict.FirstOrDefault(item => item.Key.TypeName == name).Value;
72 | }
73 |
74 | return null;
75 | }
76 |
77 | // 类型兼容性判断(支持泛型判断)
78 | public static bool IsCompatibleWith(this Type actual, Type target)
79 | {
80 | if (actual == null || target == null)
81 | return false;
82 |
83 | if (actual == target)
84 | return true;
85 |
86 | if (actual.IsGenericType && target.IsGenericType)
87 | {
88 | if (actual.GetGenericTypeDefinition() != target.GetGenericTypeDefinition())
89 | return false;
90 |
91 | var actualArgs = actual.GetGenericArguments();
92 | var targetArgs = target.GetGenericArguments();
93 | if (actualArgs.Length != targetArgs.Length)
94 | return false;
95 |
96 | for (int i = 0; i < actualArgs.Length; i++)
97 | {
98 | if (actualArgs[i] != targetArgs[i])
99 | return false;
100 | }
101 |
102 | return true;
103 | }
104 |
105 | return target.IsAssignableFrom(actual);
106 | }
107 |
108 | // 判断一个类型是否处于另一个类型的继承链中
109 | public static bool IsInBaseTypeHierarchy(this Type type, Type baseType)
110 | {
111 | if (baseType == null || (!baseType.IsClass && !baseType.IsInterface))
112 | return false;
113 |
114 | if (type == baseType)
115 | return true;
116 |
117 | var current = type.BaseType;
118 | while (current != null)
119 | {
120 | if (current == baseType)
121 | return true;
122 | current = current.BaseType;
123 | }
124 |
125 | return baseType.IsInterface && type.GetInterfaces().Contains(baseType);
126 | }
127 |
128 | // 自定义 FirstOrDefault 带默认值
129 | public static KeyValuePair FirstOrDefaultOr(this IEnumerable> source, Func, bool> predicate, KeyValuePair defaultValue)
130 | {
131 | foreach (var item in source)
132 | {
133 | if (predicate(item))
134 | return item;
135 | }
136 | return defaultValue;
137 | }
138 | }
139 | }
140 |
--------------------------------------------------------------------------------
/UPPERIOC/UPPERIOC.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | UPPERIOC
6 | preview
7 |
8 | True
9 | net462;netstandard2.0
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | 2.0.4.62
29 | UPPERIOC
30 | Wwwwww
31 | 一个自带插件的IOC容器
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | true
43 | analyzers\dotnet\roslyn3.8\cs
44 |
45 |
46 |
47 |
48 |
49 | true
50 | analyzers\dotnet\roslyn3.8\cs
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 | true
68 | true
69 | True
70 | MIT
71 | True
72 | latest
73 | enable
74 | C:\Program Files (x86)\Microsoft SDKs\NuGetPackages
75 | UPPERIOC
76 | True
77 | true
78 | snupkg
79 | README.md
80 | False
81 | https://gitee.com/laowangm_m/upper-com-auto-test
82 | UPPERIOC.png
83 | https://gitee.com/laowangm_m/upper-com-auto-test
84 | gitee
85 | ioc
86 | 初始版本
87 | enable
88 | False
89 | 2.0.0
90 | 5d9e1ecd-9e2e-4d37-86f4-fcb71f419384
91 | zh
92 | OnOutputUpdated
93 |
94 |
95 | embedded
96 |
97 |
98 | embedded
99 |
100 |
101 | embedded
102 | True
103 |
104 |
105 | embedded
106 |
107 |
108 | True
109 | embedded
110 |
111 |
112 | embedded
113 |
114 |
115 |
116 | True
117 | \
118 |
119 |
120 |
121 |
122 |
123 | C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5.2\System.Windows.Forms.dll
124 |
125 |
126 |
127 |
128 |
129 | True
130 | \
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
--------------------------------------------------------------------------------
/TestDemo/IoCTests.cs:
--------------------------------------------------------------------------------
1 | using Xunit;
2 | using UPPERIOC.UPPER.IOC.Center.IProvider;
3 | using TestDemo.Entity;
4 | using UPPERIOC.UPPER.IOC.DefaultProvider;
5 | using System.Collections.Concurrent;
6 | using System.Threading.Tasks;
7 | using System;
8 |
9 | public class IoCTests
10 | {
11 | private readonly UPPERDefaultProvider _container;
12 |
13 | public IoCTests()
14 | {
15 | _container = new UPPERDefaultProvider();
16 | }
17 |
18 | [Fact]
19 | public void Register_And_Resolve_SimpleService()
20 | {
21 | var obj = _container.Rigister();
22 | Assert.NotNull(obj);
23 | var resolved = _container.GetInstance();
24 | Assert.NotNull(resolved);
25 | Assert.Equal("Hello", resolved.GetData());
26 | }
27 |
28 | [Fact]
29 | public void Register_And_Resolve_ComplexService_With_Dependency()
30 | {
31 | _container.Rigister();
32 | var obj = _container.Rigister();
33 |
34 | Assert.NotNull(obj);
35 | Assert.NotNull(obj.Simple);
36 | Assert.Equal("Hello", obj.Simple.GetData());
37 | }
38 |
39 | [Fact]
40 | public void Register_With_Name_And_Resolve_By_Name()
41 | {
42 | var name = "MySimple";
43 | var reg = _container.Rigister(name);
44 |
45 | var resolved = _container.GetInstance(name);
46 | Assert.NotNull(resolved);
47 | Assert.Equal("Hello", resolved.GetData());
48 | }
49 |
50 | [Fact]
51 | public void Register_Interface_And_Resolve_Concrete_Implementation()
52 | {
53 | _container.Rigister();
54 | var service = _container.GetInstanceAndSub();
55 | Assert.NotNull(service);
56 | Assert.Equal("Pong", service.Ping());
57 | }
58 |
59 | [Fact]
60 | public void Register_Multiple_Instances_Should_Be_Different_When_Single_False()
61 | {
62 | var obj1 = _container.Rigister( false);
63 | var obj2 = _container.GetInstance(typeof(SimpleService));
64 | Assert.NotNull(obj1);
65 | Assert.NotNull(obj2);
66 | Assert.NotSame(obj1, obj2);
67 | }
68 |
69 | [Fact]
70 | public void Property_Injection_Should_Work()
71 | {
72 | _container.Rigister();
73 | var result = _container.Rigister();
74 |
75 | Assert.NotNull(result);
76 | Assert.NotNull(result.InjectedProp);
77 | Assert.Equal("Hello", result.InjectedProp.GetData());
78 | }
79 | [Fact]
80 | public void Concurrent_Resolve_Should_Be_Thread_Safe()
81 | {
82 | _container.Rigister(false); // 非单例,避免因共享导致误判
83 |
84 | var exceptions = new ConcurrentQueue();
85 | var results = new ConcurrentBag();
86 |
87 | Parallel.For(0, 1000, i =>
88 | {
89 | try
90 | {
91 | var instance = _container.GetInstance();
92 | if (instance == null || instance.GetData() != "Hello")
93 | {
94 | exceptions.Enqueue(new Exception("Resolved instance invalid"));
95 | }
96 | results.Add(instance);
97 | }
98 | catch (Exception ex)
99 | {
100 | exceptions.Enqueue(ex);
101 | }
102 | });
103 |
104 | Assert.Empty(exceptions); // 不应有异常
105 | Assert.Equal(1000, results.Count); // 所有实例都应返回
106 | }
107 |
108 | [Fact]
109 | public void Concurrent_Register_And_Resolve_Should_Not_Throw()
110 | {
111 | var exceptions = new ConcurrentQueue();
112 |
113 | Parallel.For(0, 100, i =>
114 | {
115 | try
116 | {
117 | _container.Rigister(false);
118 | var resolved = _container.GetInstance();
119 | if (resolved == null || resolved.GetData() != "Hello")
120 | {
121 | exceptions.Enqueue(new Exception("Invalid resolution"));
122 | }
123 | }
124 | catch (Exception ex)
125 | {
126 | exceptions.Enqueue(ex);
127 | }
128 | });
129 |
130 | Assert.Empty(exceptions); // 并发注册和解析不应抛出异常
131 | }
132 | [Fact]
133 | public void Concurrent_Resolve_ComplexService_Should_Be_Thread_Safe()
134 | {
135 | _container.Rigister();
136 | _container.Rigister();
137 |
138 | var exceptions = new ConcurrentQueue();
139 | var results = new ConcurrentBag();
140 |
141 | Parallel.For(0, 1000, i =>
142 | {
143 | try
144 | {
145 | var instance = _container.GetInstance();
146 | if (instance == null || instance.Simple == null || instance.Simple.GetData() != "Hello")
147 | {
148 | exceptions.Enqueue(new Exception("Constructor injection failed"));
149 | }
150 | results.Add(instance);
151 | }
152 | catch (Exception ex)
153 | {
154 | exceptions.Enqueue(ex);
155 | }
156 | });
157 |
158 | Assert.Empty(exceptions);
159 | Assert.Equal(1000, results.Count);
160 | }
161 | [Fact]
162 | public void Concurrent_Resolve_PropertyInjectedService_Should_Be_Thread_Safe()
163 | {
164 | _container.Rigister();
165 | _container.Rigister();
166 |
167 | var exceptions = new ConcurrentQueue();
168 | var results = new ConcurrentBag();
169 |
170 | Parallel.For(0, 1000, i =>
171 | {
172 | try
173 | {
174 | var instance = _container.GetInstance();
175 | if (instance == null || instance.InjectedProp == null || instance.InjectedProp.GetData() != "Hello")
176 | {
177 | exceptions.Enqueue(new Exception("Property injection failed"));
178 | }
179 | results.Add(instance);
180 | }
181 | catch (Exception ex)
182 | {
183 | exceptions.Enqueue(ex);
184 | }
185 | });
186 |
187 | Assert.Empty(exceptions);
188 | Assert.Equal(1000, results.Count);
189 | }
190 |
191 | }
192 |
--------------------------------------------------------------------------------
/UPPERIOC/UPPER._Premission/Center/PremissionCenter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | using System.IO;
5 | using System.Linq;
6 | using System.Text;
7 | using UPPERIOC.UPPER.IOC.Center.IProvider;
8 | using UPPERIOC2.UPPER.Premission.IConfiguation;
9 | using UPPERIOC2.UPPER.Premission.Model;
10 | using UPPERIOC2.UPPER.Util;
11 |
12 | namespace UPPERIOC2.UPPER.Premission.Center
13 | {
14 | public class PremissionCenter
15 | {
16 | public static IContainerProvider pd;
17 | public static PremissionCenter Instance { get => pd.GetInstance(); }
18 | List users = new List();
19 | string Locatstr = "HKEY_LOCAL_MACHINE\\SOFTWARE\\";
20 | public IPremissionConfiguation c;
21 | public PermissionModel pm;
22 | RigisterObjLoad rod;
23 | public User CurrentUser;
24 | internal void Load()
25 | {
26 | var r = pd.GetAllInstance();
27 | if (r == null || r.Length == 0)
28 | {
29 | throw new Exception("请配置至少一个IPremissionConfiguation实现类于容器中");
30 | }
31 | c = r[0];
32 | rod = RigisterObjLoad.GetInstance(Locatstr+ c.ApplicationName);
33 | pm = rod.LoadObjectFromRegistry(c.ApplicationName);
34 | if (pm == null)
35 | {
36 | if (!c.AllowNull)
37 | {
38 | throw new Exception("配置异常,联系管理");
39 | }
40 | else
41 | {
42 | pm = c.InitModel();
43 | SaveChange();
44 | }
45 | //pm = new PermissionModel();
46 | }
47 | CurrentUser = c.Login(pm);
48 | if (CurrentUser == null && !c.AllowNull)
49 | {
50 | throw new Exception("登录失败");
51 | }
52 | }
53 | public void AddUserToGroup(User user, RoleGroup gp)
54 | {
55 | user.RoleGroup = gp.id;
56 | //gp.users.Add(user.id);
57 |
58 | }
59 | public void AddRoleToGroup(Role r,RoleGroup rp)
60 | {
61 | rp.Roles.Add(r.id);
62 |
63 | }
64 | public bool TryDo(int premission,Action act)
65 | {
66 | User Cu = CurrentUser;
67 | if(PermissionInterceptor.Intercept(premission, false))
68 | {
69 | act.Invoke();
70 | return true;
71 | }
72 | CurrentUser = Cu;
73 | return false;
74 | }
75 | public void Must(int premission,string def ="") {
76 | User CurrentUser = this.CurrentUser;
77 | while (true)
78 | {
79 | if (pm.rolegps.Find(item => CurrentUser?.RoleGroup == item.id)?.Roles?.Contains(premission) == true)
80 | {
81 | break;
82 | }
83 | bool r = c.NotPremission();
84 |
85 |
86 |
87 | CurrentUser = c.Login(pm,def);
88 |
89 | }
90 | }
91 | public List GetRoleByRoleGroup(RoleGroup rp)
92 | {
93 | List lr = new List();
94 |
95 |
96 | foreach (var item in rp.Roles)
97 | {
98 | var i = pm.roles.Find(item1 => item == item1.id);
99 | if (i != null)
100 | {
101 | lr.Add(i);
102 |
103 | }
104 | }
105 | return lr;
106 | }
107 | public RoleGroup AddRoleGroup(RoleGroup GroupName)
108 | {
109 | GroupName.id = pm.RoleGPid;
110 | pm.rolegps.Add(GroupName);
111 | pm.RoleGPid++;
112 | return GroupName;
113 | }
114 | public Role AddRole(Role Role)
115 | {
116 | Role.id = pm.Roleid;
117 | pm.roles.Add(Role);
118 | pm.Roleid++;
119 | return Role;
120 | }
121 | public User UpdateById(User us,string pwd = null) {
122 | var changeu = pm.users.Find(item=> item.id == us.id);
123 | changeu.Name = us.Name;
124 | changeu.RoleGroup = us.RoleGroup;
125 | if (!string.IsNullOrWhiteSpace(pwd))
126 | {
127 | string Token = HashHelper.EncryptWithSalt(c.Solt, pwd);
128 | changeu.Token = Token;
129 |
130 | }
131 | changeu.UserName = us.UserName;
132 | //changeu.ActPath = us.ActPath;
133 | if (changeu.ActPath != us.ActPath)
134 | {
135 | changeu.ActPath = AddPic(us.ActPath);
136 |
137 | }
138 | return changeu;
139 |
140 | }
141 |
142 | public Role UpdateById(Role us)
143 | {
144 | var changeu = pm.roles.Find(item => item.id == us.id);
145 | changeu.Name = us.Name;
146 | changeu.Backup = us.Backup;
147 | return changeu;
148 |
149 | }
150 | public RoleGroup UpdateById(RoleGroup us)
151 | {
152 | var changeu = pm.rolegps.Find(item => item.id == us.id);
153 | changeu.Backup= us.Backup;
154 | changeu.GpName= us.GpName;
155 | changeu.Roles= us.Roles;
156 | //changeu.users= us.users;
157 | return changeu;
158 |
159 | }
160 |
161 | public void RemoveChange() {
162 | pm = rod.LoadObjectFromRegistry(c.ApplicationName);
163 |
164 | }
165 | public string AddPic(string str)
166 | {
167 | var fi = FileUtil.RelativePathToFileInfo(str);
168 | if (fi== null || !fi.Exists)
169 | {
170 | return "";
171 | }
172 | var dpa = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, c.PicSavePath);
173 | if (!Directory.Exists(dpa))
174 | {
175 | Directory.CreateDirectory(dpa);
176 | }
177 | var dstr = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, c.PicSavePath, pm.PicNum + "");
178 | fi.CopyTo(dstr,true);
179 | pm.PicNum++;
180 | return FileUtil.FileInfoToRelativePath(new FileInfo(dstr));
181 | }
182 | public User AddUser(string UserName,string password,string ActPath,string Name)
183 | {
184 | string Token = HashHelper.EncryptWithSalt(c.Solt, password);
185 |
186 | var user= new User { id = (int)pm.Userid, UserName = UserName, Token = Token, ActPath = ActPath, Name = Name };
187 | pm.users.Add(user);
188 | pm.Userid++;
189 | user.ActPath = AddPic(user.ActPath);
190 | return user;
191 |
192 | }
193 | public bool CanInvoke(int Role ,bool needlogin, User CurrentUser = null)
194 | {
195 | if (CurrentUser == null)
196 | {
197 | CurrentUser = this.CurrentUser;
198 | }
199 | try
200 | {
201 |
202 | if (CurrentUser == null && !c.AllowNull)
203 | {
204 |
205 |
206 | //return false;
207 | }
208 | if (pm.rolegps == null && !c.AllowNull)
209 | {
210 | //CurrentUser = c.Login(pm);
211 |
212 | //return false;
213 | }
214 | if (pm.rolegps.Find(item => CurrentUser?.RoleGroup == item.id)?.Roles?.Contains(Role) == true)
215 | {
216 | return true;
217 | }
218 |
219 |
220 | // return false;
221 | }
222 | catch (Exception)
223 | {
224 |
225 | throw;
226 | }
227 | finally {
228 |
229 | if (needlogin && CurrentUser!= null)
230 | {
231 | this.CurrentUser = CurrentUser;
232 | }
233 | }
234 |
235 | bool r = c.NotPremission();
236 | CurrentUser = c.Login(pm);
237 | if (r)
238 | {
239 | //CurrentUser = c.Login(pm);
240 | return CanInvoke(Role, needlogin,CurrentUser);
241 | }
242 | return false;
243 | }
244 |
245 | public void SaveChange() {
246 |
247 | rod.SaveObjectToRegistry(c.ApplicationName, pm);
248 | }
249 | }
250 | }
251 |
--------------------------------------------------------------------------------
/UPPERIOC/Util/TranslateUtil.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Linq;
5 | using System.Net;
6 | using System.Security.Cryptography;
7 | using System.Text;
8 | using System.Threading;
9 | using System.Threading.Tasks;
10 | using UPPERIOC;
11 | using UPPERIOC.UPPER.Translate.IConfigration;
12 |
13 | namespace UPPERIOC2.UPPER.Util
14 | {
15 | public class TranslateUtil
16 | {
17 | public static string ExtractTranslation(string json,string key1)
18 | {
19 | if (string.IsNullOrWhiteSpace(json))
20 | {
21 | throw new ArgumentException("JSON cannot be null or empty", nameof(json));
22 | }
23 |
24 | string key = "\"" + key1+"\"";
25 | int keyIndex = json.IndexOf(key, StringComparison.Ordinal);
26 |
27 | if (keyIndex == -1)
28 | {
29 | return "";
30 | }
31 |
32 | // Find the start of the value after the key
33 | int startIndex = json.IndexOf(':', keyIndex) + 1;
34 |
35 | // Ensure valid value extraction
36 | if (startIndex == 0)
37 | {
38 | return "";
39 | }
40 |
41 | // Handle nested braces or direct strings
42 | int braceCount = 0;
43 | int endIndex = startIndex;
44 | bool inQuotes = false;
45 |
46 | for (int i = startIndex; i < json.Length; i++)
47 | {
48 | char currentChar = json[i];
49 |
50 | if (currentChar == '"' && (i == 0 || json[i - 1] != '\\'))
51 | {
52 | inQuotes = !inQuotes;
53 | }
54 |
55 | if (!inQuotes)
56 | {
57 | if (currentChar == '{')
58 | {
59 | braceCount++;
60 | }
61 | else if (currentChar == '}')
62 | {
63 | braceCount--;
64 | }
65 |
66 | if (braceCount == 0 && (currentChar == '}' || currentChar == ','))
67 | {
68 | endIndex = i + 1;
69 | break;
70 | }
71 | }
72 | }
73 | string result = json.Substring(startIndex, endIndex - startIndex).Trim();
74 |
75 | // Return the result, or a message if no valid value was found
76 | return string.IsNullOrEmpty(result) ? "" : result.Replace("[", "").Replace("\"", "").Replace("\"", "").Replace("]", "").Replace(",", "");
77 |
78 | }
79 | static object tl = new object();
80 | public static string Transcale(string q)
81 | {
82 | var cof = UPPERIOCApplication.Container.GetInstanceAndSub();
83 | if (cof == null)
84 | {
85 | return q;
86 | }
87 | if (cof.FromLanguage == cof.ToLanguage)
88 | {
89 | return q;
90 | }
91 | lock (tl)
92 | {
93 | Dictionary dic = new Dictionary();
94 | string url = "https://openapi.youdao.com/api";
95 | string appKey = cof.APPKey;
96 | string appSecret = cof.APPSeret;
97 | string salt = DateTime.Now.Millisecond.ToString();
98 |
99 | dic.Add("from", cof.FromLanguage);
100 | dic.Add("to", cof.ToLanguage);
101 | dic.Add("signType", "v3");
102 | TimeSpan ts = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc));
103 | long millis = (long)ts.TotalMilliseconds;
104 | string curtime = Convert.ToString(millis / 1000);
105 | dic.Add("curtime", curtime);
106 | string signStr = appKey + Truncate(q) + salt + curtime + appSecret; ;
107 | string sign = ComputeHash(signStr, new SHA256CryptoServiceProvider());
108 | dic.Add("q", UrlEncode(q));
109 | dic.Add("appKey", appKey);
110 | dic.Add("salt", salt);
111 | dic.Add("sign", sign);
112 | dic.Add("vocabId", "您的用户词表ID");
113 | string re = Post(url, dic);
114 | Thread.Sleep(1000);
115 | Console.WriteLine(re);
116 | return ExtractTranslation(re, "translation");
117 | }
118 | }
119 | public static string UrlEncode(string value)
120 | {
121 | if (string.IsNullOrEmpty(value))
122 | {
123 | return string.Empty;
124 | }
125 |
126 | StringBuilder encoded = new StringBuilder();
127 | foreach (char c in value)
128 | {
129 | if (IsSafe(c))
130 | {
131 | encoded.Append(c);
132 | }
133 | else
134 | {
135 | // Convert character to its hexadecimal representation
136 | encoded.Append($"%{(int)c:X2}");
137 | }
138 | }
139 | return encoded.ToString();
140 | }
141 |
142 | private static bool IsSafe(char c)
143 | {
144 | // Safe characters as per URL encoding rules
145 | return char.IsLetterOrDigit(c) || "-_.~".IndexOf(c) >= 0;
146 | }
147 |
148 | protected static string ComputeHash(string input, HashAlgorithm algorithm)
149 | {
150 | Byte[] inputBytes = Encoding.UTF8.GetBytes(input);
151 | Byte[] hashedBytes = algorithm.ComputeHash(inputBytes);
152 | return BitConverter.ToString(hashedBytes).Replace("-", "");
153 | }
154 | protected static string Post(string url, Dictionary dic)
155 | {
156 | string result = "";
157 | HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
158 | req.Method = "POST";
159 | req.ContentType = "application/x-www-form-urlencoded";
160 | StringBuilder builder = new StringBuilder();
161 | int i = 0;
162 | foreach (var item in dic)
163 | {
164 | if (i > 0)
165 | builder.Append("&");
166 | builder.AppendFormat("{0}={1}", item.Key, item.Value);
167 | i++;
168 | }
169 | byte[] data = Encoding.UTF8.GetBytes(builder.ToString());
170 | req.ContentLength = data.Length;
171 | using (Stream reqStream = req.GetRequestStream())
172 | {
173 | reqStream.Write(data, 0, data.Length);
174 | reqStream.Close();
175 | }
176 | HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
177 | if (resp.ContentType.ToLower().Equals("audio/mp3"))
178 | {
179 | SaveBinaryFile(resp, "合成的音频存储路径");
180 | }
181 | else
182 | {
183 | Stream stream = resp.GetResponseStream();
184 | using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
185 | {
186 | result = reader.ReadToEnd();
187 | }
188 | return (result);
189 | }
190 | return null;
191 | }
192 |
193 | protected static string Truncate(string q)
194 | {
195 | if (q == null)
196 | {
197 | return null;
198 | }
199 | int len = q.Length;
200 | return len <= 20 ? q : (q.Substring(0, 10) + len + q.Substring(len - 10, 10));
201 | }
202 |
203 | private static bool SaveBinaryFile(WebResponse response, string FileName)
204 | {
205 | string FilePath = FileName + DateTime.Now.Millisecond.ToString() + ".mp3";
206 | bool Value = true;
207 | byte[] buffer = new byte[1024];
208 |
209 | try
210 | {
211 | if (File.Exists(FilePath))
212 | File.Delete(FilePath);
213 | Stream outStream = System.IO.File.Create(FilePath);
214 | Stream inStream = response.GetResponseStream();
215 |
216 | int l;
217 | do
218 | {
219 | l = inStream.Read(buffer, 0, buffer.Length);
220 | if (l > 0)
221 | outStream.Write(buffer, 0, l);
222 | }
223 | while (l > 0);
224 |
225 | outStream.Close();
226 | inStream.Close();
227 | }
228 | catch
229 | {
230 | Value = false;
231 | }
232 | return Value;
233 | }
234 | }
235 | }
236 |
--------------------------------------------------------------------------------