Преобразовать объект класса в индекс класса - PullRequest
0 голосов
/ 07 февраля 2020
Class Person {
  int Id 
  string Name 
  string Address 
  // etc 
}

вместо доступа к нему как Person.Id, Person.Name, Person.Address. Я хочу получить к нему доступ через индекс, как Person ['Id'], Person ['Name']. Есть ли какое-либо преобразование codegen или linq для этого.

Ответы [ 5 ]

4 голосов
/ 07 февраля 2020

Вы можете использовать Json.NET JObject класс

Person p = new Person() { Id = 1, Address = "A", Name = "B" };
var obj = JObject.FromObject(p);
Console.WriteLine(obj["Id"]); //1
2 голосов
/ 07 февраля 2020

Это чистая C# реализация:

class Program
{
    static void Main(string[] args)
    {
        Person person = new Person
        {
            Id = 1,
            Name = "test",
            Address = "tost"
        };

        Console.WriteLine(person["Id"]);
        person["Id"] = 5;
        Console.WriteLine(person["Id"]);
    }
}

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Address { get; set; }

    public object this[string propertyName]
    {
        get
        {
            return this.GetType().GetProperty(propertyName).GetValue(this);
        }

        set
        {
            this.GetType().GetProperty(propertyName).SetValue(this, value);
        }
    }
}

Вывод:

1

5

Важное замечание:

Я бы никогда не рекомендовал использовать это в производственной среде, если вы хотите использовать систему, реализованную вручную, по крайней мере, вам следует обрабатывать извлечения типов и свойств, чтобы избежать потребления большего объема памяти, чем необходимые и превышающие накладные расходы.

0 голосов
/ 07 февраля 2020

Индексатор не облегчит сравнение данных. Я подозреваю, что real вопрос в том, как обрабатывать данные в C# так же, как работают Python DataFrames. ADO. NET предоставляет класс DataTable начиная с. NET 1.0. Он предназначен больше для обработки базы данных, чем для анализа данных, хотя он поддерживает такие операции, как поиск, слияние и разложение.

Для анализа данных новый пакет Microsoft.Data.Analysis предоставляет класс DataFrame .

При этом для чтения свойств по имени вам придется использовать Отражение, дорогая операция. Один из способов сделать это дешевле - кэшировать дескрипторы типов и свойств. Вместо того, чтобы писать код самостоятельно, вы можете использовать библиотеку Mar c Gravel FastMember , которая делает именно это. При этом вы можете создать тип TypeAccessor или ObjectAccessor и читать свойства по имени, например:

var wrapped = ObjectAccessor.Create(obj);
string propName = // something known only at runtime 
Console.WriteLine(wrapped[propName]);

Если вы хотите читать из нескольких объектов, вам понадобится TypeAccessor:

var accessor = TypeAccessor.Create(type); 
string propName = // something known only at runtime 
while( /* some loop of data */ )
{ 
  accessor[obj, propName] = rowValue; 
}

Библиотека не такая большая. Если вам не разрешено использовать пакеты NuGet, вы можете скопировать код в свой проект.

0 голосов
/ 07 февраля 2020

Использование отражения и индексаторов:

public class ExampleClass{

    public object this[string name]
    {
        get
        {
            var properties = typeof(ExampleClass)
                    .GetProperties(BindingFlags.Public | BindingFlags.Instance);

            foreach (var property in properties)
            {
                if (property.Name == name && property.CanRead)
                    return property.GetValue(this, null);
            }

            throw new ArgumentException("Can't find property");

        }
        set {
            return;
        }
    }
}
0 голосов
/ 07 февраля 2020

Если вам нужно получить доступ к свойству как к значению переменной, найдите отражение.

ex) string a = "Name"; Человек [а]

...