c# - 如果需要,在转换 Type 时通过 Ref 设置属性
问题描述
我有一系列复杂的类,我在这里放了一个可以编译和工作的最小示例:
public class DataClass : IMPropertyAsStringSettable
{
public int num { get; set; }
public string code { get; set; }
public PartClass part { get; set; }
public MemberClass member { get; set; }
public DataClass()
{
part = new PartClass();
member = new MemberClass();
}
}
public class PartClass : IMPropertyAsStringSettable
{
public int seriesNum { get; set; }
public string seriesCode { get; set; }
}
public class MemberClass : IMPropertyAsStringSettable
{
public int versionNum { get; set; }
public SideClass side { get; set; }
public MemberClass()
{
side = new SideClass();
}
}
public class SideClass : IMPropertyAsStringSettable
{
public string firstDetail { get; set; }
public string secondDetail { get; set; }
public bool include { get; set; }
}
您看到的接口在与 all 相同的命名空间中实现如下:
public interface IMPropertyAsStringSettable { }
public static class PropertyAsStringSettable
{
public static void SetPropertyAsString(this IMPropertyAsStringSettable self, string propertyName, string value)
{
var property = TypeDescriptor.GetProperties(self)[propertyName];
var convertedValue = property.Converter.ConvertFrom(value);
property.SetValue(self, convertedValue);
}
}
我试图通过实际从字符串中调用属性名称来实现设置“按引用”的属性值类型。我正在尝试但无法解决两个问题。我无法设置“链接”属性值,或者由于我在接口中的错误,实现中的某些内容无法正常工作。其次,同样重要的是,我无法读取和转换属性,即我只有字符串作为值,有时属性是 bool、int、double、DateTime 等。现在,我知道转换是一个大课题,所以我想尝试读取属性类型并通过 try/catch 进行转换,但我做不到。
这就是我想要实现的(基于上面的代码):
static int Main(string[] args)
{
//just initializing the whole thing without
//setting values to properties
DataClass myClass = new DataClass()
{
part = new PartClass(),
member = new MemberClass()
{
side = new SideClass()
}
};
// here I read from a source names and values.....
//and I am trying to populate like this:
myClass.SetPropertyAsString("include", "true"); //this property is in SideClass, and also a bool
myClass.SetPropertyAsString("seriesNum", "88"); //this property is in PartClass and an int..
直接用作:
//This should print "True"
Console.WriteLine("myClass member side include = " + myClass.member.side.include.ToString());
Console.ReadKey();
return 0;
}
我真的希望有人可以提供帮助,我不是这方面的专家;如果您可以提供基于上述内容的工作代码,我将不胜感激。谢谢你们
注意:使用反射可以更好地工作(尝试为我在 JSON 字符串中找到的所有属性分配值)。欢迎任何帮助..
解决方案
如果属性不是顶级属性,那么我们需要通向目标属性的路径,在我们的例子中路径是member:side:include
. 我在这里:
用作分隔符。
//top-level property
myClass.SetPropertyAsString("num", "88");
//nested properties
myClass.SetPropertyAsString("member:side:include", "true");
myClass.SetPropertyAsString("part:seriesNum", "15");
然后修改反射代码,使其可以沿着给定的路径前进:
//will handle both nested and top-level properties
public static void SetPropertyAsString(this IMPropertyAsStringSettable self, string propertyName, string value) {
//current, is in a way, the property iterator
var current = self;
var keys = propertyName.Split(":");
//iterate over keys till the key before last -since the last key is the target property-
foreach (var key in keys[0..^1]) {
var property = current.GetType().GetProperty(key);
current = property.GetValue(current) as IMPropertyAsStringSettable;
}
var targetProperty = current.GetType().GetProperty(keys.Last());
//convert the input value to the data type of the target property, and set it to the target property
targetProperty.SetValue(current, Convert.ChangeType(value, targetProperty.PropertyType));
}
编辑:对于 C# < 8.0
根据您的评论,您使用的是 C# 版本 < 8.0,其中原始响应中使用的某些功能不可用(例如 range operator ^
)。我在 上编译了以下内容.NET 4.7.2
,C# 7.3
并产生了相同的结果。
public static void SetPropertyAsString(this IMPropertyAsStringSettable self, string propertyName, string value) {
var current = self;
var keys = propertyName.Split(':');
for (var i = 0; i < keys.Length - 1; i++) {
var property = current.GetType().GetProperty(keys[i]);
current = property.GetValue(current) as IMPropertyAsStringSettable;
}
var targetProperty = current.GetType().GetProperty(keys[keys.Length - 1]);
targetProperty.SetValue(current, Convert.ChangeType(value, targetProperty.PropertyType));
}
推荐阅读
- html - 在 x 方向上倾斜看起来像这样的最佳方法是什么?
- javascript - 使用 webpack 丑化节点模块
- c# - 属性“item_no”是对象的关键信息的一部分,不能修改。但是我根本没有在更新时触及该属性
- python - Python Turtle 模块无法在 Windows 10 上运行
- python - 如何在 python 中创建空字典并在运行程序时将数据插入其中?
- c# - 如何使用 OOXML 删除 WordProcessingML 中的 TableRow?
- sql - ORACLE SQL 中的 NOT IN with NULL 值困境
- c# - T-SQL PRINT 语句是否在任何地方记录?
- linux - 在将数据从内核复制到用户期间,非阻塞 I/O 会进入睡眠状态吗?
- python - Pandas 命名聚合不适用于重采样 agg