| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207 |
- using PlcUiControl;
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.ComponentModel.Design.Serialization;
- using System.IO;
- using System.Linq;
- using System.Windows.Forms;
- [TypeConverter(typeof(NodeConverter))]
- [Serializable]
- public class Node
- {
- private string _value;
- public static readonly string NodeFilePath = @"D:\XmlParser\ReadNodes.txt";
- public static List<string> AllNodes=new List<string>();
- public static bool EnableDesignTimeValidation { get; set; } = true; // 默认开启,提醒开发者
- public string Value
- {
- get => _value;
- set
- {
- value=value.Trim();
- if (string.IsNullOrWhiteSpace(value))
- {
- throw new ArgumentException("地址不能为空");
- }
- if (EnableDesignTimeValidation && !IsValidNode(value))
- {
- throw new ArgumentException($"地址\"{value}\"无效,请输入正确的地址,或导入XML后选择对应的地址。");
- //var dr = MessageBox.Show($"地址\"{value}\"无效,是否坚持绑定此地址?", "询问", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
- //if (dr == DialogResult.No)
- //{
- // return;
- //}
- }
- _value = value;
- }
- }
- public string Name { get; set; }
- public NodeType Type { get; set; }
- public string Comment { get; set; }
- public Node()
- {
- }
- public Node(string value)
- {
- _value = value;
- Name = null;
- Type = NodeType.Unspecified;
- Comment = null;
- }
- public Node(string value, NodeType nodeType)
- {
- _value = value;
- //Name = StringExtensions.AfterLast(value, '.');
- Type = nodeType;
- Comment = null;
- }
- public Node(string value,NodeType nodeType,string comment)
- {
- _value = value;
- Name = StringExtensions.AfterLast(value, '.');
- Type = nodeType;
- Comment = comment;
- }
- public override string ToString()
- {
- return _value;
- }
- private bool IsValidNode(string input)
- {
- try
- {
- if (AllNodes.Contains(input))//先在内存中查找
- {
- return true;
- }
- if (!File.Exists(NodeFilePath))
- {
- throw new FileNotFoundException("ReadNodes.txt 文件未找到", NodeFilePath);
- }
- // 读取文件所有行并比较(忽略前后空格)
- return File.ReadLines(NodeFilePath)
- .Any(line => line.Trim() == input.Trim());
- }
- catch (Exception ex)
- {
- // 可以记录日志或抛出异常
- Console.WriteLine("验证地址时出错:" + ex.Message);
- return false;
- }
- }
- }
- public class NodeConverter : TypeConverter
- {
- // 1. 允许展开属性
- public override bool GetPropertiesSupported(ITypeDescriptorContext context)
- {
- return true; // 关键:返回 true 才能展开
- }
- // 2. 返回子属性集合
- public override PropertyDescriptorCollection GetProperties(
- ITypeDescriptorContext context,
- object value,
- Attribute[] attributes)
- {
- // 获取 Node 类的所有公共属性
- return TypeDescriptor.GetProperties(value, attributes)
- .Sort(new string[] { "Name", "Type", "Comment", "Value" }); // 可选排序
- }
- public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
- {
- // 支持从字符串转换
- if (sourceType == typeof(string))
- {
- return true;
- }
- return base.CanConvertFrom(context, sourceType);
- }
- public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
- {
- // 当用户输入字符串时,尝试构造 ReadNode 对象
- if (value is string str)
- {
- str= str.Trim();
- if (!string.IsNullOrEmpty(str))
- return new Node { Value = str };
- else
- return null;
- }
- return base.ConvertFrom(context, culture, value);
- }
- public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
- {
- if (destinationType == typeof(InstanceDescriptor) && value is Node n)
- {
- var ctor1 = typeof(Node).GetConstructor(new[] { typeof(string), typeof(NodeType), typeof(string) });
- if (ctor1 != null)
- {
- return new InstanceDescriptor(ctor1, new object[] { n.Value, n.Type, n.Comment });
- }
- else
- {
- MessageBox.Show("ConvertTo ctor1 Failed");
- }
- // 回退到单参数构造函数(更安全)
- var ctor2 = typeof(Node).GetConstructor(new[] { typeof(string), typeof(NodeType) });
- if (ctor2 != null)
- {
- return new InstanceDescriptor(ctor2, new object[] { n.Value, n.Type });
- }
- else
- {
- MessageBox.Show("ConvertTo ctor2 Failed");
- }
-
- }
- return base.ConvertTo(context, culture, value, destinationType);
- }
- public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
- {
- // 明确告诉设计器:可以生产new Node(...) 代码
- if (destinationType == typeof(InstanceDescriptor))
- {
- return true; // ✅ 关键!允许代码生成
- }
- if (destinationType == typeof(string))//如果返回True,那么设计器会调用ConvertTo 进行字符串格式化。
- {
- return false; // ✅ 关键!
- }
- return base.CanConvertTo(context, destinationType);
- }
- }
- public enum NodeType
- {
-
- BOOL=0,
- BYTE,
- WORD,
- DWORD,
- LWORD,
- SINT,
- USINT,
- INT,
- UINT,
- DINT,
- UDINT,
- LINT,
- ULINT,
- REAL,
- LREAL,
- TIME,//UINT32
- STRING,
- Unspecified = -1,
- }
|