c# - 使用反射显示来自不同自定义类的数据
问题描述
我想创建一个显示对象中包含的信息的方法,该方法将动态地与任何对象一起工作。我在处理属于其他自定义类的属性时遇到问题。在下面的示例中,Person
hasPhones
和Occupations
which 都是其他类。数据显示时,当前屏幕上的值为:
TestReflection.Person
Name: Mary
Phones: TestReflection.Phones
Occupations: TestReflection.Occupations
它只显示类的名称,例如TestReflection.Phones
,而不是该对象内的数据。
如何更改此代码以显示此类信息?
TestReflection.Person
Name: Mary
Phones:
TestReflection.Phones
Type: 1
Number: 555XYZ
Occupations:
TestReflection.Occupations
Type: 5
Description: Secretary
这是我的代码:
class Program
{
static void Main(string[] args)
{
List<Person> listPeson = new List<Person>();
var person1 = new Person();
person1.Name = "Mary";
person1.Phones = new Phones { new Phone { Type = 1, Number = "555XYZ" } };
person1.Occupations = new Occupations {new Occupation { Type = 5, Description = "Secretary" }};
listPeson.Add(person1);
DynamicExport(listPeson);
Console.ReadLine();
}
public static void DynamicExport<T>(List<T> listReg)
{
for (int i = 0; i < listReg.Count; i++)
{
Console.WriteLine(listReg[i].GetType());
foreach (var item in listReg[i].GetType().GetProperties())
{
Console.WriteLine($"{item.Name}: {item.GetValue(listReg[i], null)}");
}
}
}
}
class Person
{
public string Name { get; set; }
public Phones Phones { get; set; }
public Occupations Occupations { get; set; }
}
class Phones : List<Phone> { }
class Phone
{
public int Type { get; set; }
public string Number { get; set; }
}
class Occupations : List<Occupation> { }
class Occupation
{
public int Type { get; set; }
public string Description { get; set; }
}
解决方案
我对您的问题进行了一些编辑-希望我正确理解了您。
如果要导出数据
If your question is really about displaying data, then there are better ways to do it than creating your own export method. The format you are trying to display looks similar to YAML. There's also JSON and XML. Using one of these libraries is probably better than writing your own method:
If you want to learn more about reflection
Maybe you're interested in learning more about reflection, and the export is just an example to play around with it. In that case, let's look at this line:
Console.WriteLine($"{item.Name}: {item.GetValue(listReg[i], null)}");
$"{item.GetValue(listReg[i], null)}"
ends up calling person1.Phones.ToString()
. The default behavior of ToString
just displays the type name. You could override that behavior, like this:
class Phones : List<Phone>
{
public override string ToString()
{
return Program.DynamicExportToString(this);
// ... where DynamicExportToString is a modified version of DynamicExport that
// builds and returns a string rather than sending it directly to the Console.
}
}
Maybe you want to be able to handle any class, even when you cannot override ToString
in all of the classes you might export. Then you will need to put some additional logic in the DynamicExport
method, because...
$"{item.Name}: {item.GetValue(listReg[i], null)}"
... doesn't work for every situation. We need to display different things depending on the type of the property.
- Consider how you want to handle null values. Maybe something like
$"{item.Name}: <null>"
- Use your existing
$"..."
code if the type is...- a primitive type.
DateTime
String
- ... or a
Nullable<>
of one of those types.
- If the type implements
IEnumerable
, loop over the contents of the collection and recursively call your export code for each element.- It's important to check for this interface after you've checked if the type is a
String
, becauseString
implementsIEnumerable
.
- It's important to check for this interface after you've checked if the type is a
- Otherwise, recursively call your export code on this value.
When you call your export code recursively, it would be wise to guard against infinite loops. If the object you're trying to export contains a circular reference - you could quickly wind up with a StackOverflowException
. To avoid this, maintain a stack of objects that have already been visited.
I think the above advice is generally applicable whenever you're using reflection to traverse an object graph - whether it's for serialization or any other purpose. I hope this helps!
推荐阅读
- javascript - 无服务器框架在AWS lambda上部署的express.js应用程序中发送 HTTP 请求时出现问题
- android - 华为P20屏幕方向异常
- javascript - 如何在角度打字稿中访问画中画相关功能?
- javascript - TypeError: Object(…) 不是函数
- python - python cffi被windows defender隔离
- php - $_POST 表单高级安全性
- exchangewebservices - 使用 ews 禁用 Outlook 电子邮件转发
- watchkit - 如何检测在表格行控制器中添加的 WKInterfaceGroup 上的点击?
- c# - How to sort User and Role in core Identity
- javascript - 无论总数如何,Javascript 都获得 100%