c#泛型类型类无法获取属性值
使用c#反射获取并设置泛型对象中泛型字段的值。但是我找不到任何方法来获取这些字段的属性值。下面的代码示例:c#泛型类型类无法获取属性值,c#,object,generics,reflection,field,C#,Object,Generics,Reflection,Field,使用c#反射获取并设置泛型对象中泛型字段的值。但是我找不到任何方法来获取这些字段的属性值。下面的代码示例: public class Foo<T> { public bool IsUpdated { get; set; } } public abstract class ValueObjec<T> { public string InnerValue { get; set; } } public class ItemList: ValueObject&
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;
}
您必须在
itemField
处使用FieldType
属性而不是GetType()
来获取Foo
类型
编辑:
必须获取字段类型的实例
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));
您的对象不是itemField
,而是该对象上itemField
的值。所以把它传进来;并将结果视为布尔值,如果可能:
var isUpdated = false;
object foo = itemField.GetValue(itemList);
...
isUpdated = (bool)isUpdatedProp.GetValue(foo, null);
最后:
if (isUpdated == "false") isUpdatedProp.SetValue(itemField, "true");
同样,对象是itemList
,属性不是字符串
if (!isUpdated) isUpdatedProp.SetValue(foo, true);
如果您制作了
Foo:IFoo
,其中IFoo
是一个非通用接口,则会更容易:
interface IFoo { bool IsUpdated {get; set; } }
然后它变成:
var foo = (IFoo)itemField.GetValue(itemList);
if(!foo.IsUpdated) foo.IsUpdated = true;
最后,请注意,
FirstName
和LastName
如果您没有为它们分配任何内容,则它们将为空。让我花两分钱尝试为您提供另一种解决问题的观点
我不会为此使用反射:为什么不使用接口键入这些对象
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()
公共接口IUpdatable
{
bool已更新{get;set;}
}
公共接口IManyUpdatable
{
IEnumerable可更新文件{get;}
}
公共静态类可更新扩展
{
公共静态无效切换已更新(此IUpdatable可更新)
{
if(可更新!=null)
updateable.IsUpdated=!updateable.IsUpdated
}
公共静态void toggleUpdateables(此IEnumerable Updateables)
{
foreach(可更新文件中的变量可更新)
ToggleUpdated()
}
}
公共类Foo:IUpdatable
{
公共bool已更新{get;set;}
}
公共类项目列表:ValueObject
{
公众名字;
公众姓氏;
IEnumerable imanyUpdateable.Updateables=>new[]{FirstName,LastName}
}
// ... 在代码库中的某个地方:
itemList.ToggleUpdateables()
我不确定我是否领会了这个想法,但你似乎在过度设计,无缘无故地绕过打字 顺便提一下,为什么要将所有内容都转换为字符串,而不是只使用
bool
值?您可能指的是itemField.FieldType
/itemField.PropertyType
而不是itemField.GetType()
;很难说,因为itemType
实际上并没有在您的代码中定义。基本上,如果您提供一个而不仅仅是一个无法编译的代码片段,那么帮助您会容易得多。我们无法分辨哪些错误在您的真实代码中,哪些错误只是您在编写问题时添加的。@HimBromBeere我怀疑foreach(var itemList…
中有打字错误,我认为应该是foreach(var itemField…
继承的属性不会由GetProperty
返回,除非您使用flattHierarchy
绑定标志:BindingFlags.Instance | BindingFlags.Public | BindingFlags.flattHierarchy
使用itemField.FieldType.GetProperty(“IsUpdate”),它只是返回了正确的属性。但抛出了一个错误“对象与目标类型不匹配”。每当调用GetValue()方法itemField.FieldType.GetProperty(“IsUpdate”)。GetValue(itemField,null)只需使用GetValue(itemField)
而不是GetValue(itemField,null)
它抛出异常还是什么?将结果与字符串进行比较。等于@kaskiet项字段
不是Foo
的实例,这就是抛出异常的原因。谢谢你的想法,但我必须使用反射来解决这个问题problem@Kasguest顺便说一句,对我来说,你现在的问题似乎是XY问题。谁知道呢如果你解释你的问题而不是你试图解决的问题,我可以说服你在很多情况下避免反思:谢谢你的指导,非常具体。试试看!
var foo = (IFoo)itemField.GetValue(itemList);
if(!foo.IsUpdated) foo.IsUpdated = true;
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()