【问题标题】:List content of an object dynamicly动态列出对象的内容
【发布时间】:2011-09-06 10:23:19
【问题描述】:

有两种对象:

public class Toto
{
    String test1 = "";
    int test2 = 0;
}

public class Titi
{
    String testA = "";
    int testB = 0;
}

我将创建一个允许我动态检查任何对象内容的方法。例如:

public void checkDatas(Object o)

在这个方法中,我会访问 test1 并检查它的值,然后是 test2,然后是 testA,最后是 testB。像这样的东西 (Object) Object.getMember(new Toto(), "test1")

我在反射过程中找到了一些解释,但没有任何作用。

有人有想法吗?

提前致谢。

【问题讨论】:

  • 请提供实际问题,这样会更容易帮助您。

标签: c# .net reflection dynamic .net-4.0


【解决方案1】:

我真的不知道你为什么想要这样的东西,如果你有,请提供这些信息。但是你不能这样做吗:

var type = o.GetType();
var members = type.GetMembers(BindingFlags.NonPublic|BindingFlags.Public);
foreach(var member in members)
{
    var field = type.GetField(member.Name);
    Console.WriteLine(field.GetValue(o));
}

更新:使用 MemberInfo 而不是 PropertyInfo,您仍然应该向我们提供有关您在做什么的信息。

【讨论】:

  • 它们不是属性,所以 GetProperties 不会返回任何东西。
  • 更新了示例以改用MemberInfo
【解决方案2】:

您可以这样做,但如果不了解“检查每个成员”是什么,我真的无法为您提供更多帮助:

public void CheckMembers(object o)
{
    foreach(var member in o.GetType().GetFields())
    {
        object value = member.GetValue(o);
    }
}

【讨论】:

  • 检查每个成员意味着我想访问它的值以便与一个好的值进行比较。
  • 嗯,您可以使用member.Namemember.GetValue(obj),但这将是一种复杂的方法,将名称查找到好的值,然后查找到您得到的值。很可能有更好的方法来做到这一点。
  • o.GetType().GetFields().Length 返回 0,但我可以通过 o. 访问成员... :(
  • 您可能需要使用允许您指定绑定标志以查看私有字段的重载 - 请参阅@M4N 的答案。
【解决方案3】:

尝试以这种方式访问​​实例:

public void checkDatas(Object o)
{
    if (o is Toto)
    {
       (o as Toto).test1 = 0;
    }

    if (o is Titi)
    {
       (o as Titi).testA = "";
    }
}

请注意,我假设这些字段是公开的。

【讨论】:

  • 这不是一个解决方案,因为这意味着我需要在“checkDatas”中指定每种对象。
【解决方案4】:

如果您知道类型,则可以使用 string value = typeof(Toto).GetField("test1").GetValue(instance); 实现这种反射,但仅使用方法重载会更有效:

public void CheckObject(Toto toto) { }
public void CheckObject(Titi titi) { }

或者更好的是,让两个对象都符合一个接口,比如ICheckable,这样你只需要实现一个方法:

public void CheckObject(ICheckable checkable);

【讨论】:

  • 一个简短的问题。如果instance 被声明为object,运行时如何确定要运行哪个重载?它甚至会起作用吗?我想你会得到一个编译错误。
  • @Tomas - 我们的想法是不要以object 的身份传递实例。
【解决方案5】:

首先,面向对象编程,一个对象不允许任何外部资源查看其私有字段。

对于类似的需求,例如表达一个对象的内容 ToString() 方法可以被重写。请记住,对象必须决定要公开哪个值。

所以在你的情况下,你可以像这样覆盖 ToString。

public override string ToString()
{
     return String.Format("Value of test1={0}\nValue of test2={1}", test1, test2);
}

或者尝试像 RevealValues() 这样的方法来实现接口。在您以后可能要检查的每个类中实现此接口。

【讨论】:

    【解决方案6】:

    您可以使用反射来读取(未知)对象的成员,例如:

    public class Toto
    {
        String test1 = "aaa";
        int test2 = 0;
    }
    
    // -------------
    
    Toto t = new Toto();
    
    var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
    foreach (FieldInfo field in t.GetType().GetFields(flags))
    {
        Console.WriteLine(field.Name + " : " + field.GetValue(t));
    }
    

    这会产生以下输出:

    test1 : aaa
    test2 : 0
    

    注意:如果你的类有私有字段,那么在调用Type.GetFields()时必须指定正确的BindingFlags,如上所示。

    【讨论】:

      【解决方案7】:

      首先,我会尝试在您要检查的对象中实现一些共性。

      例如,Toto 定义 test1 而 Titi 定义 testA 有必要吗?如果 Toto 和 Titi 都定义了 test1,有可能吗?这样您就可以为两者创建通用接口:

      public class Toto
      {
          private string test1 = "Hello from Toto object"; 
          public string Test1 { get { return this.test1; } }
      }
      
      public class Titi
      {
          private string test1 = "Hello from Titi object"; 
          public string Test1 { get { return this.test1; } }
      }
      

      现在你可以定义一个通用接口了:

      public interface ICheerfulObject
      {
          string Test1 { get; }
      }
      

      让你的两个类都像这样实现这个接口:

      public class Toto: ICheerfulObject
      {
           ....
      }
      
      pulbic class Titi: ICheerfulObject
      {
           ....
      }
      

      然后你可以这样做:

      public void CheckData(ICheerfulObject o)
      {
          string data = o.Test1;
      }
      

      如果这种情况无效并且您确实需要使用反射,请尝试以下操作:

       public void CheckData(object o)
       {
           PropertyInfo property = o.GetType().GetProperty("Test1");  //Get used to using public properties.
           string data = (string)property.GetValue(o, null);
       }
      

      【讨论】:

        猜你喜欢
        • 2012-12-22
        • 1970-01-01
        • 2017-09-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-02-25
        • 2022-01-20
        相关资源
        最近更新 更多