gpt4 book ai didi

c# - 除了 System.Type 之外没有任何更多信息的 Cast 对象

转载 作者:行者123 更新时间:2023-11-30 17:19:22 26 4
gpt4 key购买 nike

对于 SO question我最近写了一个通用扩展方法,它应该从另一个对象加载一个对象,即将源的所有属性分配给目标,如果该属性是引用类型,则递归地这样做。我使用反射已经走得很远了,但是当涉及到引用类型的属性类型时我遇到了一个问题,这是我的第一种方法:

第一种方法:

    public static void Load<T>(this T target, T source, bool deep)
{
foreach (PropertyInfo property in typeof(T).GetProperties())
{
if (property.CanWrite && property.CanRead)
{
if (!deep || property.PropertyType.IsPrimitive || property.PropertyType == typeof(String))
{
property.SetValue(target, property.GetValue(source, null), null);
}
else
{
property.GetValue(target, null).Load(property.GetValue(source, null), deep);
}
}
}
}

这里的问题是 PropertyInfo.GetValue 返回一个对象,随后 T 在递归调用中将等于 object 并且我不能再获取对象实际具有的属性。

我设想了一种解决方法,它要求您显式传递类型,这是非常多余的,因为理论上应该可以在没有以下情况的情况下进行管理:

    public static void Load<T>(this T target, Type type, T source, bool deep)
{
foreach (PropertyInfo property in type.GetProperties())
{
if (property.CanWrite && property.CanRead)
{
if (!deep || property.PropertyType.IsPrimitive || property.PropertyType == typeof(String))
{
property.SetValue(target, property.GetValue(source, null), null);
}
else
{
object targetPropertyReference = property.GetValue(target, null);
targetPropertyReference.Load(targetPropertyReference.GetType(), property.GetValue(source, null), deep);
}
}
}
}

我也尝试过使用dynamic targetPropertyReference,但是我得到了一个运行时异常,指出找不到Load 方法,这真令人恼火。

除此之外 Convert.ChangeType 也很容易返回一个血腥的 object 并且我似乎无法以其他方式将对象转换为它的本来面目。当然,我已经在网上寻找过这个问题的答案,但到目前为止我一直没有成功。

最佳答案

我没有查看完整代码或考虑实现此类方案的全部后果(编辑:如果存在循环引用会发生什么?),但我可以针对您的特定问题提供两个简短修复 问题:

选项 1:回避问题

使用提供的“正常”参数的运行时类型,而不是类型参数

替换:

typeof(T).GetProperties()

与:

// You need null-checks around this:
// you can't realistically continue if target is null anyway.
target.GetType().GetProperties()

这当然会在您的代码中引入一个次要语义更改,因为它可以防止人们想要传递 Giraffe 但只想要 Animal 的情况 属性复制过来。如果 sourcetarget 是不同的运行时类型(具有不同的属性),它也会爆炸,但你可以轻松解决这个问题(例如找到最深的公共(public)基类型并使用它的属性。


选项 2:更多反射/动态

当然,另一个解决方案是使用 MakeGenericMethod 来允许“动态”提供类型参数。这保持了代码的原始语义(未经测试):

typeof(MyClass).GetMethod("Load")
.MakeGenericMethod(property.PropertyType)
.Invoke(null, property.GetValue(target, null),
property.GetValue(source, null), deep);

顺便说一句,没有您不能使用dynamic 来完成非常相似的事情的理由。我怀疑您正在尝试将调用“作为”扩展方法,but that won't work .只需尝试正常的“静态方法”语法即可。

关于c# - 除了 System.Type 之外没有任何更多信息的 Cast 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4937650/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com