[英]c# generic type class cannot get the property value
Using c# reflection to get & set the value of the generic fields inside a generic object. 使用c#reflection来获取和设置泛型对象中的通用字段的值。 But I cannot find any way to get the property value of these fields .
但我找不到任何方法来获得这些字段的属性值 。 The code example below:
下面的代码示例:
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;
}
Problem Getting the 'null' item at the line (*). 问题在行(*)处获取“null”项。
itemField.GetType() always return the System.Reflection.RtFieldInfo type but not the Foo type. itemField.GetType()始终返回System.Reflection.RtFieldInfo类型,但不返回Foo类型。
I already tried using itemField.FieldType.GetProperty("IsUpdated"), it worked when returned the correct property. 我已经尝试过使用itemField.FieldType.GetProperty(“IsUpdated”),它在返回正确的属性时起作用。 But threw an error "Object does not match target type."
但抛出错误“对象与目标类型不匹配”。 whenever call GetValue() method itemField.FieldType.GetProperty("IsUpdated").GetValue(itemField, null)
每次调用GetValue()方法itemField.FieldType.GetProperty(“IsUpdated”)。GetValue(itemField,null)
Much more appreciated if getting help from anyone! 如果得到任何人的帮助,我们将非常感激!
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");
}
}
let's unpack this one thing at a time: 让我们一次解开这一件事:
var isUpdatedProp = itemField.GetType().GetProperty("IsUpdated");
You should never need to use .GetType()
on a member; 你永远不需要在成员上使用
.GetType()
; you want .FieldType
or .PropertyType
(for properties). 你想
.FieldType
或.PropertyType
(房产)。 And nameof
is great: 并且
nameof
很棒:
var isUpdatedProp = itemField.FieldType.GetProperty(nameof(Foo<string>.IsUpdated));
( string
here is a dummy) (这里的
string
是假的)
Then: 然后:
isUpdated = isUpdatedProp.GetValue(itemField, null).ToString();
It isn't itemField
that is your object - that's whatever the value of itemField
on that object gives you. itemField
不是你的对象 - 这就是该对象上itemField
的值给你的东西。 So pass that in; 所以通过; and treat the result as a boolean , if possible:
如果可能的话,将结果视为布尔值 :
var isUpdated = false;
object foo = itemField.GetValue(itemList);
...
isUpdated = (bool)isUpdatedProp.GetValue(foo, null);
Finally: 最后:
if (isUpdated == "false") isUpdatedProp.SetValue(itemField, "true");
Once again, the object is itemList
, and the property isn't a string
对象再次是
itemList
,属性不是string
if (!isUpdated) isUpdatedProp.SetValue(foo, true);
It would be easier if you made Foo<T> : IFoo
where IFoo
is a non-generic interface: 如果你做了
Foo<T> : IFoo
,其中IFoo
是一个非通用接口会更容易:
interface IFoo { bool IsUpdated {get; set; } }
Then it becomes: 然后它变成:
var foo = (IFoo)itemField.GetValue(itemList);
if(!foo.IsUpdated) foo.IsUpdated = true;
Finally, note that FirstName
and LastName
will be null if you haven't assigned them anything. 最后,请注意,如果您没有为它们指定任何内容,
FirstName
和LastName
将为null 。
You must use the FieldType
property instead of GetType()
at itemField
to get Foo
type. 您必须在
itemField
使用FieldType
属性而不是GetType()
来获取Foo
类型。
https://msdn.microsoft.com/en-us/library/system.reflection.fieldinfo.fieldtype(v=vs.110).aspx https://msdn.microsoft.com/en-us/library/system.reflection.fieldinfo.fieldtype(v=vs.110).aspx
EDIT: You must get the instance of the field type 编辑:您必须获取字段类型的实例
var foo = itemField.GetValue(itemList);
var isUpdated = isUpdatedProp.GetValue(foo);
Final result should be like this: 最终结果应该是这样的:
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);
}
}
Let me throw my two cents on trying to give you another point of view to solve the problem. 让我把两分钱放在试图给你另一个观点来解决问题上。
I wouldn't use reflection for this: why don't you type those objects with interfaces? 我不会为此使用反射 :为什么不用接口键入这些对象?
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()
I'm not sure if I've caught the idea, but it seems like you're overengineering and bypassing typing for no reason! 我不确定我是否已经抓住了这个想法,但似乎你是过度工程并且无缘无故地绕过打字!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.