简体   繁体   中英

Convert class object to class index

Class Person {
  int Id 
  string Name 
  string Address 
  // etc 
}

instead of accessing it like Person.Id, Person.Name, Person.Address. I want to access it via index just like Person['Id'], Person['Name']. Is there any codegen or linq conversion for this.

You can use Json.NET 's JObject class

Person p = new Person() { Id = 1, Address = "A", Name = "B" };
var obj = JObject.FromObject(p);
Console.WriteLine(obj["Id"]); //1

This is a pure C# implementation:

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);
        }
    }
}

Output:

1

5

Important note:

I would never recommend to use this in a production environment, if you want to use an handly implemented system, atleast you should handle types and properties extractions to avoid consuming more memory than needed and exceeding overheads.

Using reflection and indexers:

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

An indexer won't make data comparison any easier. I suspect the real question is how to handle data in C# the same way Python's DataFrames work. ADO.NET provides the DataTable class since .NET 1.0. It's meant more for database processing than data analysis, altough it does support operations like searching, merging and diffing.

For data anlysis, the new Microsoft.Data.Analysis package provides the DataFrame class.

That said, to read properties by name, you'll have to use Reflection, an expensive operation. One way to make this cheaper is to cache type and property descriptors. Instead of writing the code yourself though, you can use Marc Gravel's FastMember library that does just that. With this, you can create a TypeAccessor or ObjectAccessor type and read properties by name, eg :

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

If you want to read from multiple objects, you'll need a TypeAccessor :

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

The library isn't that big. If you aren't allowed to use NuGet packages, you could copy the code into your project.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM