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&

使用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;
}

您必须在
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()