Extract TagItem class, Update Nullable

This commit is contained in:
ChsBuffer
2021-03-27 17:40:18 +08:00
parent 2ab693facf
commit 3cbd5af9a3
17 changed files with 214 additions and 80 deletions

View File

@@ -190,7 +190,7 @@ namespace Netch.Controllers
string fileName;
try
{
fileName = p.MainModule!.FileName;
fileName = p.MainModule?.FileName ?? throw new Exception(); // TODO what's this exception?
}
catch (Exception e)
{

View File

@@ -16,13 +16,13 @@ namespace Netch.Forms
_parent = parent;
}
protected override void OnLoad(EventArgs e)
protected override void OnLoad(EventArgs? e)
{
base.OnLoad(e);
Parent_Move(null!, null!);
}
private void Parent_Move(object sender, EventArgs e)
private void Parent_Move(object? sender, EventArgs? e)
{
var cl = Location;
var fl = _parent.Location;
@@ -32,7 +32,7 @@ namespace Netch.Forms
Location = cl;
}
private void Parent_Activated(object sender, EventArgs e)
private void Parent_Activated(object? sender, EventArgs? e)
{
SetWindowPos(Handle,
HWND.HWND_TOPMOST,
@@ -51,7 +51,7 @@ namespace Netch.Forms
SetWindowPosFlags.SWP_NOACTIVATE | SetWindowPosFlags.SWP_NOMOVE | SetWindowPosFlags.SWP_NOSIZE | SetWindowPosFlags.SWP_SHOWWINDOW);
}
private void richTextBox1_TextChanged(object sender, System.EventArgs e)
private void richTextBox1_TextChanged(object? sender, EventArgs? e)
{
if (!checkBox1.Checked)
return;
@@ -60,19 +60,19 @@ namespace Netch.Forms
richTextBox1.ScrollToCaret();
}
private void Notifycation_Load(object sender, EventArgs e)
private void Notifycation_Load(object? sender, EventArgs? e)
{
_parent.LocationChanged += Parent_Move;
_parent.SizeChanged += Parent_Move;
_parent.Activated += Parent_Activated;
}
protected override void OnClosing(CancelEventArgs e)
protected override void OnClosing(CancelEventArgs? e)
{
_parent.Activated -= Parent_Activated;
_parent.LocationChanged -= Parent_Move;
_parent.SizeChanged -= Parent_Move;
base.OnClosing(e);
base.OnClosing(e!);
}
}
}

View File

@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Drawing;
using System.IO;
using System.Linq;
@@ -234,8 +235,12 @@ namespace Netch.Forms
}
}
private void AddServerToolStripMenuItem_Click(object sender, EventArgs e)
private void AddServerToolStripMenuItem_Click([NotNull] object? sender, EventArgs? e)
{
if (sender == null)
throw new ArgumentNullException(nameof(sender));
// TODO get Util from Tag
var s = ((ToolStripMenuItem) sender).Text;
var start = s.IndexOf("[", StringComparison.Ordinal) + 1;
@@ -321,12 +326,12 @@ namespace Netch.Forms
{
Task.Run(() =>
{
void OnNewVersionNotFound(object o, EventArgs args)
void OnNewVersionNotFound(object? o, EventArgs? args)
{
NotifyTip(i18N.Translate("Already latest version"));
}
void OnNewVersionFoundFailed(object o, EventArgs args)
void OnNewVersionFoundFailed(object? o, EventArgs? args)
{
NotifyTip(i18N.Translate("New version found failed"), info: false);
}
@@ -661,7 +666,7 @@ namespace Netch.Forms
ServerHelper.DelayTestHelper.TestDelayFinished += OnTestDelayFinished;
_ = Task.Run(ServerHelper.DelayTestHelper.TestAllDelay);
void OnTestDelayFinished(object o1, EventArgs e1)
void OnTestDelayFinished(object? o1, EventArgs? e1)
{
Refresh();
@@ -900,8 +905,11 @@ namespace Netch.Forms
return profile;
}
private async void ProfileButton_Click(object sender, EventArgs e)
private async void ProfileButton_Click([NotNull] object? sender, EventArgs? e)
{
if (sender == null)
throw new ArgumentNullException(nameof(sender));
var profileButton = (Button) sender;
var profile = (Profile?) profileButton.Tag;
var index = ProfileTable.Controls.IndexOf(profileButton);
@@ -1317,7 +1325,7 @@ namespace Netch.Forms
UpdateChecker.NewVersionFound -= OnUpdateCheckerOnNewVersionFound;
}
void OnUpdateCheckerOnNewVersionFound(object o, EventArgs eventArgs)
void OnUpdateCheckerOnNewVersionFound(object? o, EventArgs? eventArgs)
{
NotifyTip($"{i18N.Translate(@"New version available", ": ")}{UpdateChecker.LatestVersionNumber}");
NewVersionLabel.Text = i18N.Translate("New version available");

View File

@@ -149,7 +149,7 @@ namespace Netch.Forms.Mode
Close();
}
private void RemarkTextBox_TextChanged(object sender, EventArgs e)
private void RemarkTextBox_TextChanged(object? sender, EventArgs? e)
{
BeginInvoke(new Action(() =>
{
@@ -195,7 +195,8 @@ namespace Netch.Forms.Mode
foreach (string dir in Directory.GetDirectories(directory))
ScanDirectory(dir, list, maxCount);
list.AddRange(Directory.GetFiles(directory).Select(Path.GetFileName).Where(s => s.EndsWith(".exe")).Select(s => s.ToRegexString()));
list.AddRange(
Directory.GetFiles(directory).Select(s => Path.GetFileName(s)).Where(s => s.EndsWith(".exe")).Select(s => s.ToRegexString()));
if (maxCount != 0 && list.Count > maxCount)
throw new Exception("The number of results is greater than maxCount");

View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@@ -1,6 +1,7 @@
using System;
using System.IO;
using System.Windows.Forms;
using Netch.Models;
using Netch.Properties;
using Netch.Utils;
@@ -8,26 +9,7 @@ namespace Netch.Forms.Mode
{
public partial class Route : Form
{
class Item
{
private string _text;
public Item(int value, string text)
{
_text = text;
Value = value;
}
public string Text
{
get => i18N.Translate(_text);
set => _text = value;
}
public int Value { get; set; }
}
private readonly Item[] _items = {new(1, "Proxy Rule IPs"), new(2, "Bypass Rule IPs")};
private readonly TagItem<int>[] _items = {new(1, "Proxy Rule IPs"), new(2, "Bypass Rule IPs")};
private readonly Models.Mode? _mode;
@@ -41,8 +23,8 @@ namespace Netch.Forms.Mode
InitializeComponent();
Icon = Resources.icon;
comboBox1.DataSource = _items;
comboBox1.ValueMember = "Value";
comboBox1.DisplayMember = "Text";
comboBox1.ValueMember = nameof(TagItem<int>.Value);
comboBox1.DisplayMember = nameof(TagItem<int>.Text);
}
private void Route_Load(object sender, EventArgs e)
@@ -110,12 +92,9 @@ namespace Netch.Forms.Mode
Close();
}
private void RemarkTextBox_TextChanged(object sender, EventArgs e)
private void RemarkTextBox_TextChanged(object? sender, EventArgs? e)
{
BeginInvoke(new Action(() =>
{
FilenameTextBox.Text = ModeEditorUtils.GetCustomModeRelativePath(RemarkTextBox.Text);
}));
BeginInvoke(new Action(() => { FilenameTextBox.Text = ModeEditorUtils.GetCustomModeRelativePath(RemarkTextBox.Text); }));
}
}
}

View File

@@ -6,6 +6,7 @@ using System.Linq;
using System.Net;
using System.Threading.Tasks;
using System.Windows.Forms;
using Netch.Models;
using Netch.Properties;
using Netch.Utils;
@@ -99,10 +100,7 @@ namespace Netch.Forms
BindTextBox<string>(AclAddrTextBox, s => true, s => Global.Settings.ACL = s, Global.Settings.ACL);
BindListComboBox(LanguageComboBox,
o => Global.Settings.Language = o.ToString(),
i18N.GetTranslateList().Cast<object>().ToArray(),
Global.Settings.Language);
BindListComboBox(LanguageComboBox, o => Global.Settings.Language = o.ToString(), i18N.GetTranslateList(), Global.Settings.Language);
#endregion
@@ -128,7 +126,7 @@ namespace Netch.Forms
BindListComboBox(ProcessProxyProtocolComboBox,
s => Global.Settings.ProcessProxyProtocol = (PortType) Enum.Parse(typeof(PortType), s.ToString(), false),
Enum.GetNames(typeof(PortType)).Cast<object>().ToArray(),
Enum.GetNames(typeof(PortType)),
Global.Settings.ProcessProxyProtocol.ToString());
#endregion
@@ -324,14 +322,19 @@ namespace Netch.Forms
_saveActions.Add(control, c => save.Invoke(((RadioButton) c).Checked));
}
private void BindListComboBox(ComboBox control, Action<object> save, object[] values, object value, string propertyName = "SelectedItem")
private void BindListComboBox<T>(ComboBox comboBox, Action<T> save, IEnumerable<T> values, T value) where T : notnull
{
if (control.DropDownStyle != ComboBoxStyle.DropDownList)
if (comboBox.DropDownStyle != ComboBoxStyle.DropDownList)
throw new ArgumentOutOfRangeException();
control.Items.AddRange(values);
_saveActions.Add(control, c => save.Invoke(((ComboBox) c).SelectedItem));
Load += (_, _) => { control.SelectedItem = value; };
var tagItems = values.Select(o => new TagItem<T>(o, o.ToString()!)).ToArray();
comboBox.Items.AddRange(tagItems.Cast<object>().ToArray());
comboBox.ValueMember = nameof(TagItem<T>.Value);
comboBox.DisplayMember = nameof(TagItem<T>.Text);
_saveActions.Add(comboBox, c => save.Invoke(((TagItem<T>) ((ComboBox) c).SelectedItem).Value));
Load += (_, _) => { comboBox.SelectedItem = tagItems.SingleOrDefault(t => t.Value.Equals(value)); };
}
private void BindComboBox(ComboBox control, Func<string, bool> check, Action<string> save, string value, object[]? values = null)

View File

@@ -16,8 +16,11 @@ namespace Netch.Models.GitHubRelease
Suffix = suffix;
}
public static SuffixVersion Parse(string input)
public static SuffixVersion Parse(string? input)
{
if (input == null)
throw new ArgumentNullException(nameof(input));
var split = input.Split('-');
var dotNetVersion = Version.Parse(split[0]);
var preRelease = split.ElementAtOrDefault(1) ?? string.Empty;
@@ -39,7 +42,7 @@ namespace Netch.Models.GitHubRelease
}
}
public int CompareTo(object obj)
public int CompareTo(object? obj)
{
if (obj is not SuffixVersion version)
throw new ArgumentOutOfRangeException();

View File

@@ -1,11 +1,18 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
namespace Netch.Models.GitHubRelease
{
public class VersionComparer : IComparer<object>
{
public int Compare(object x, object y)
public int Compare(object? x, object? y)
{
if (x == null)
throw new ArgumentNullException(nameof(x));
if (y == null)
throw new ArgumentNullException(nameof(y));
return VersionUtil.CompareVersion(x.ToString(), y.ToString());
}
}

View File

@@ -23,7 +23,7 @@ namespace Netch.Models.GitHubRelease
/// <returns> =0:versions are equal</returns>
/// <returns> &gt;0:version1 is greater</returns>
/// <returns> &lt;0:version2 is greater</returns>
public static int CompareVersion(string v1, string v2)
public static int CompareVersion(string? v1, string? v2)
{
var version1 = SuffixVersion.Parse(v1);
var version2 = SuffixVersion.Parse(v2);

19
Netch/Models/TagItem.cs Normal file
View File

@@ -0,0 +1,19 @@
using Netch.Utils;
namespace Netch.Models
{
internal class TagItem<T>
{
private readonly string _text;
public TagItem(T value, string text)
{
_text = text;
Value = value;
}
public string Text => i18N.Translate(_text);
public T Value { get; }
}
}

View File

@@ -17,9 +17,7 @@ namespace Netch.Utils
/// <returns>适配器名称</returns>
public static string GetName(string componentId)
{
var registry = Registry.LocalMachine.OpenSubKey($"{NETWORK_KEY}\\{componentId}\\Connection");
return registry.GetValue("Name", "").ToString();
return Registry.LocalMachine.OpenSubKey($"{NETWORK_KEY}\\{componentId}\\Connection")?.GetValue("Name")?.ToString() ?? "";
}
public static string? GetAdapterId(params string[] componentIds)

View File

@@ -17,7 +17,7 @@ namespace Netch.Utils
.GetExportedTypes()
.Where(type => type.GetInterfaces().Contains(typeof(IServerUtil)));
ServerUtils = serversUtilsTypes.Select(t => (IServerUtil) Activator.CreateInstance(t)).OrderBy(util => util.Priority);
ServerUtils = serversUtilsTypes.Select(t => (IServerUtil) Activator.CreateInstance(t)!).OrderBy(util => util.Priority);
}
public static Type GetTypeByTypeName(string typeName)

View File

@@ -32,7 +32,7 @@ namespace Netch.Utils
try
{
list.AddRange(JsonSerializer.Deserialize<List<ShadowsocksConfig>>(text)
list.AddRange(JsonSerializer.Deserialize<List<ShadowsocksConfig>>(text)!
.Select(server => new Shadowsocks
{
Hostname = server.server,

View File

@@ -1,6 +1,7 @@
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Drawing;
using System.IO;
using System.Linq;
@@ -116,7 +117,10 @@ namespace Netch.Utils
public static string GetFileVersion(string file)
{
return File.Exists(file) ? FileVersionInfo.GetVersionInfo(file).FileVersion : string.Empty;
if (File.Exists(file))
return FileVersionInfo.GetVersionInfo(file).FileVersion ?? "";
return "";
}
public static void DrawCenterComboBox(object sender, DrawItemEventArgs e)
@@ -223,7 +227,7 @@ namespace Netch.Utils
}
}
public static async Task ProcessRunHiddenAsync(string fileName, string? arguments = null, bool print = true)
public static async Task ProcessRunHiddenAsync(string fileName, string arguments = "", bool print = true)
{
var p = new Process
{

View File

@@ -1,6 +1,5 @@
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
@@ -30,13 +29,6 @@ namespace Netch.Utils
return req;
}
public static IPEndPoint BestLocalEndPoint(IPEndPoint remoteIPEndPoint)
{
var testSocket = new Socket(remoteIPEndPoint.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
testSocket.Connect(remoteIPEndPoint);
return (IPEndPoint) testSocket.LocalEndPoint;
}
/// <summary>
/// 异步下载
/// </summary>
@@ -44,9 +36,9 @@ namespace Netch.Utils
/// <returns></returns>
public static async Task<byte[]> DownloadBytesAsync(HttpWebRequest req)
{
using var webResponse = (HttpWebResponse) await req.GetResponseAsync();
using var memoryStream = new MemoryStream();
using var input = webResponse.GetResponseStream();
using var webResponse = req.GetResponseAsync();
await using var memoryStream = new MemoryStream();
await using var input = webResponse.Result.GetResponseStream();
await input.CopyToAsync(memoryStream);
return memoryStream.ToArray();
@@ -77,7 +69,7 @@ namespace Netch.Utils
public static async Task<string> DownloadStringAsync(HttpWebRequest req, string encoding = "UTF-8")
{
using var webResponse = await req.GetResponseAsync();
using var responseStream = webResponse.GetResponseStream();
await using var responseStream = webResponse.GetResponseStream();
using var streamReader = new StreamReader(responseStream, Encoding.GetEncoding(encoding));
return await streamReader.ReadToEndAsync();
@@ -92,8 +84,8 @@ namespace Netch.Utils
public static async Task DownloadFileAsync(HttpWebRequest req, string fileFullPath)
{
using var webResponse = (HttpWebResponse) await req.GetResponseAsync();
using var input = webResponse.GetResponseStream();
using var fileStream = File.OpenWrite(fileFullPath);
await using var input = webResponse.GetResponseStream();
await using var fileStream = File.OpenWrite(fileFullPath);
await input.CopyToAsync(fileStream);
fileStream.Flush();

View File

@@ -88,7 +88,7 @@ namespace Netch.Utils
var a = new StringBuilder();
foreach (var t in text)
if (t is string)
a.Append(Data.Contains(t) ? Data[t].ToString() : t);
a.Append(Data[t]?.ToString() ?? t);
else
a.Append(t);