c# 泛型类型 class 无法获取 属性 值
c# generic type class cannot get the property value
使用 C# 反射获取和设置通用对象内通用字段的值。但是我找不到任何方法来 获取这些字段的 属性 值 。下面的代码示例:
public class Foo<T>
{
public bool IsUpdated { get; set; }
}
public abstract class ValueObjec<T>
{
public string InnerValue { get; set; }
}
public class ItemList: ValueObject<ItemList>
{
public Foo<string> FirstName;
public Foo<string> LastName;
}
问题
在 (*) 行获取 'null' 项目。
itemField.GetType() 总是 return System.Reflection.RtFieldInfo 类型而不是 Foo 类型.
我已经尝试使用 itemField.FieldType.GetProperty("IsUpdated"),当 return 编辑正确的 属性 时它起作用了。但是每当调用 GetValue() 方法时都会抛出错误 "Object does not match target type."
itemField.FieldType.GetProperty("IsUpdated").GetValue(itemField, null)
如果能得到任何人的帮助,将不胜感激!
var itemList = new ItemList();
foreach (var itemField in itemList.GetType().GetFields())
{
var isUpdated = "false";
var isUpdatedProp = itemField.GetType().GetProperty("IsUpdated"); // (*) return null from here
if (isUpdatedProp != null)
{
isUpdated = isUpdatedProp.GetValue(itemField, null).ToString();
if (isUpdated == "false") isUpdatedProp.SetValue(itemField, "true");
}
}
foreach (var itemField in itemList.GetType().GetFields())
{
var isUpdated = "false";
var isUpdatedProp = itemField.FieldType.GetProperty("IsUpdated");
if (isUpdatedProp != null)
{
isUpdated = isUpdatedProp.GetValue(itemField, null).ToString(); (*) // throw error "Object does not match target type"
if (isUpdated == "false") isUpdatedProp.SetValue(itemField, "true");
}
}
您必须在 itemField
处使用 FieldType
属性 而不是 GetType()
才能获得 Foo
类型。
https://msdn.microsoft.com/en-us/library/system.reflection.fieldinfo.fieldtype(v=vs.110).aspx
编辑:
您必须获取字段类型的实例
var foo = itemField.GetValue(itemList);
var isUpdated = isUpdatedProp.GetValue(foo);
最终结果应该是这样的:
var itemList = new ItemList();
foreach (var itemField in itemList.GetType().GetFields())
{
var isUpdatedProp = itemField.FieldType.GetProperty("IsUpdated");
if (isUpdatedProp != null)
{
var foo = itemField.GetValue(itemList);
isUpdated = (bool)isUpdatedProp.GetValue(foo);
if (!isUpdated) isUpdatedProp.SetValue(foo, true);
}
}
让我们一次打开这个东西:
var isUpdatedProp = itemField.GetType().GetProperty("IsUpdated");
您应该从不需要对成员使用.GetType()
;你想要 .FieldType
或 .PropertyType
(对于属性)。 nameof
很棒:
var isUpdatedProp = itemField.FieldType.GetProperty(nameof(Foo<string>.IsUpdated));
(string
这里是一个假人)
然后:
isUpdated = isUpdatedProp.GetValue(itemField, null).ToString();
它不是 itemField
那是你的对象 - 那是 itemField
在那个对象 上给你的任何值。所以把它传进去;并将结果 视为布尔值 ,如果可能的话:
var isUpdated = false;
object foo = itemField.GetValue(itemList);
...
isUpdated = (bool)isUpdatedProp.GetValue(foo, null);
最后:
if (isUpdated == "false") isUpdatedProp.SetValue(itemField, "true");
再次强调,对象是 itemList
,属性 不是 string
if (!isUpdated) isUpdatedProp.SetValue(foo, true);
如果你制作 Foo<T> : IFoo
会更容易,其中 IFoo
是一个 non-generic 接口:
interface IFoo { bool IsUpdated {get; set; } }
然后变成:
var foo = (IFoo)itemField.GetValue(itemList);
if(!foo.IsUpdated) foo.IsUpdated = true;
最后,请注意 FirstName
和 LastName
如果您没有为它们分配任何内容,它们将是 null。
让我花两分钱尝试为您提供解决问题的另一种观点。
我不会为此使用 反射:你为什么不用接口来键入那些对象?
public interface IUpdatable
{
bool IsUpdated { get; set; }
}
public interface IManyUpdatable
{
IEnumerable<IUpdatable> Updatables { get; }
}
public static class UpdatableExtensions
{
public static void ToggleUpdated(this IUpdatable updatable)
{
if(updatable != null)
updatable.IsUpdated = !updatable.IsUpdated
}
public static void ToggleUpdatables(this IEnumerable<IUpdatable> updatables)
{
foreach(var updatable in updatables)
updatable.ToggleUpdated()
}
}
public class Foo<T> : IUpdatable
{
public bool IsUpdated { get; set; }
}
public class ItemList: ValueObject<ItemList>
{
public Foo<string> FirstName;
public Foo<string> LastName;
IEnumerable<IUpdatable> IManyUpdatable.Updatables => new [] { FirstName, LastName }
}
// ... somewhere in your code base:
itemList.ToggleUpdatables()
我不确定我是否理解了这个想法,但您似乎过度设计并无缘无故地绕过了打字!
使用 C# 反射获取和设置通用对象内通用字段的值。但是我找不到任何方法来 获取这些字段的 属性 值 。下面的代码示例:
public class Foo<T>
{
public bool IsUpdated { get; set; }
}
public abstract class ValueObjec<T>
{
public string InnerValue { get; set; }
}
public class ItemList: ValueObject<ItemList>
{
public Foo<string> FirstName;
public Foo<string> LastName;
}
问题 在 (*) 行获取 'null' 项目。
itemField.GetType() 总是 return System.Reflection.RtFieldInfo 类型而不是 Foo 类型.
我已经尝试使用 itemField.FieldType.GetProperty("IsUpdated"),当 return 编辑正确的 属性 时它起作用了。但是每当调用 GetValue() 方法时都会抛出错误 "Object does not match target type." itemField.FieldType.GetProperty("IsUpdated").GetValue(itemField, null)
如果能得到任何人的帮助,将不胜感激!
var itemList = new ItemList();
foreach (var itemField in itemList.GetType().GetFields())
{
var isUpdated = "false";
var isUpdatedProp = itemField.GetType().GetProperty("IsUpdated"); // (*) return null from here
if (isUpdatedProp != null)
{
isUpdated = isUpdatedProp.GetValue(itemField, null).ToString();
if (isUpdated == "false") isUpdatedProp.SetValue(itemField, "true");
}
}
foreach (var itemField in itemList.GetType().GetFields())
{
var isUpdated = "false";
var isUpdatedProp = itemField.FieldType.GetProperty("IsUpdated");
if (isUpdatedProp != null)
{
isUpdated = isUpdatedProp.GetValue(itemField, null).ToString(); (*) // throw error "Object does not match target type"
if (isUpdated == "false") isUpdatedProp.SetValue(itemField, "true");
}
}
您必须在 itemField
处使用 FieldType
属性 而不是 GetType()
才能获得 Foo
类型。
https://msdn.microsoft.com/en-us/library/system.reflection.fieldinfo.fieldtype(v=vs.110).aspx
编辑: 您必须获取字段类型的实例
var foo = itemField.GetValue(itemList);
var isUpdated = isUpdatedProp.GetValue(foo);
最终结果应该是这样的:
var itemList = new ItemList();
foreach (var itemField in itemList.GetType().GetFields())
{
var isUpdatedProp = itemField.FieldType.GetProperty("IsUpdated");
if (isUpdatedProp != null)
{
var foo = itemField.GetValue(itemList);
isUpdated = (bool)isUpdatedProp.GetValue(foo);
if (!isUpdated) isUpdatedProp.SetValue(foo, true);
}
}
让我们一次打开这个东西:
var isUpdatedProp = itemField.GetType().GetProperty("IsUpdated");
您应该从不需要对成员使用.GetType()
;你想要 .FieldType
或 .PropertyType
(对于属性)。 nameof
很棒:
var isUpdatedProp = itemField.FieldType.GetProperty(nameof(Foo<string>.IsUpdated));
(string
这里是一个假人)
然后:
isUpdated = isUpdatedProp.GetValue(itemField, null).ToString();
它不是 itemField
那是你的对象 - 那是 itemField
在那个对象 上给你的任何值。所以把它传进去;并将结果 视为布尔值 ,如果可能的话:
var isUpdated = false;
object foo = itemField.GetValue(itemList);
...
isUpdated = (bool)isUpdatedProp.GetValue(foo, null);
最后:
if (isUpdated == "false") isUpdatedProp.SetValue(itemField, "true");
再次强调,对象是 itemList
,属性 不是 string
if (!isUpdated) isUpdatedProp.SetValue(foo, true);
如果你制作 Foo<T> : IFoo
会更容易,其中 IFoo
是一个 non-generic 接口:
interface IFoo { bool IsUpdated {get; set; } }
然后变成:
var foo = (IFoo)itemField.GetValue(itemList);
if(!foo.IsUpdated) foo.IsUpdated = true;
最后,请注意 FirstName
和 LastName
如果您没有为它们分配任何内容,它们将是 null。
让我花两分钱尝试为您提供解决问题的另一种观点。
我不会为此使用 反射:你为什么不用接口来键入那些对象?
public interface IUpdatable
{
bool IsUpdated { get; set; }
}
public interface IManyUpdatable
{
IEnumerable<IUpdatable> Updatables { get; }
}
public static class UpdatableExtensions
{
public static void ToggleUpdated(this IUpdatable updatable)
{
if(updatable != null)
updatable.IsUpdated = !updatable.IsUpdated
}
public static void ToggleUpdatables(this IEnumerable<IUpdatable> updatables)
{
foreach(var updatable in updatables)
updatable.ToggleUpdated()
}
}
public class Foo<T> : IUpdatable
{
public bool IsUpdated { get; set; }
}
public class ItemList: ValueObject<ItemList>
{
public Foo<string> FirstName;
public Foo<string> LastName;
IEnumerable<IUpdatable> IManyUpdatable.Updatables => new [] { FirstName, LastName }
}
// ... somewhere in your code base:
itemList.ToggleUpdatables()
我不确定我是否理解了这个想法,但您似乎过度设计并无缘无故地绕过了打字!