使用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;
}
问题 得到&#39; null&#39;第(*)行的项目。
itemField.GetType()始终返回 System.Reflection.RtFieldInfo 类型,但不返回 Foo 类型。
我已经尝试过使用itemField.FieldType.GetProperty(&#34; IsUpdated&#34;),它在返回正确的属性时起作用。但每当调用GetValue()方法时,抛出错误&#34;对象与目标类型不匹配。&#34; itemField.FieldType.GetProperty(&#34; IsUpdated&#34;)。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");
}
}
答案 0 :(得分:4)
让我们一次解开这一件事:
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
是非通用接口,那会更容易:
interface IFoo { bool IsUpdated {get; set; } }
然后它变成:
var foo = (IFoo)itemField.GetValue(itemList);
if(!foo.IsUpdated) foo.IsUpdated = true;
最后请注意,FirstName
和LastName
将为空,如果您尚未为其指定任何内容。
答案 1 :(得分:1)
您必须在FieldType
使用GetType()
属性而不是itemField
来获取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);
}
}
答案 2 :(得分:1)
让我抛出两分钱试图给你另一个观点来解决问题。
我不会为此使用 reflection :为什么不用接口键入这些对象?
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()
我不确定我是否抓住了这个想法,但似乎你是过度工程并且无缘无故地绕过打字!