Список содержимого объекта динамически - PullRequest
1 голос
/ 01 июня 2011

Есть два вида объектов:

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")

Я нашел некоторые объяснения процесса отражения, но ничего не работает.

У кого-нибудь есть идея?

Заранее спасибо.

Ответы [ 7 ]

3 голосов
/ 01 июня 2011

Вы можете использовать отражение для чтения членов (неизвестных) объектов, например:

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, как показано выше.

2 голосов
/ 01 июня 2011

Вы можете сделать что-то подобное, но, не зная больше о том, что такое «проверка каждого участника», я не могу вам больше помочь:

public void CheckMembers(object o)
{
    foreach(var member in o.GetType().GetFields())
    {
        object value = member.GetValue(o);
    }
}
1 голос
/ 01 июня 2011

Прежде всего, я бы попытался реализовать некоторую общность в объектах, которые вы хотите проверить.

Например, необходимо ли, чтобы Toto определял test1, а Titi определял testA? Было бы возможно, если бы Тото и Тити определили оба 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;
}

Если этот сценарий недействителен и вам действительно нужно использовать Reflection, попробуйте следующее:

 public void CheckData(object o)
 {
     PropertyInfo property = o.GetType().GetProperty("Test1");  //Get used to using public properties.
     string data = (string)property.GetValue(o, null);
 }
1 голос
/ 01 июня 2011

Прежде всего, при объектно-ориентированном программировании, объект не позволит никаким внешним источникам просматривать его частные поля.

Для аналогичных нужд, например, для выражения содержимого объекта, метод ToString () можетбыть переопределенным.Помните, что объект должен решить, какое значение выставлять.

Так что в вашем случае вы можете переопределить ToString следующим образом.

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

Или попытаться реализовать интерфейс как с методом, подобным RevealValues ​​().Реализуйте этот интерфейс в каждом классе, который вы, возможно, захотите изучить позже.

1 голос
/ 01 июня 2011

Хотя вы можете добиться этого отражения, используя string value = typeof(Toto).GetField("test1").GetValue(instance);, если вы знаете типы, гораздо эффективнее просто использовать перегрузки методов:

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

А еще лучше, чтобы оба объекта соответствовали интерфейсу, скажем, ICheckable, и таким образом вам нужно реализовать только один метод:

public void CheckObject(ICheckable checkable);
1 голос
/ 01 июня 2011

Попробуйте использовать экземпляры доступа следующим образом:

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

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

Обратите внимание, что я предполагаю, что поля являются открытыми.

1 голос
/ 01 июня 2011

Я действительно не могу сказать, почему вы хотите что-то подобное, пожалуйста, предоставьте эту информацию, если она у вас есть. Но вы не можете сделать что-то вроде этого:

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, и вы все равно должны предоставить нам информацию о том, что вы делаете.

...