I want to index class properties like an array.
Public class Foo
{
propery p1{get;set;}
propery p3{get;set;}
propery p3{get;set;}
.
.
.
.
}
I wan to index every propery like an array FOO.p1=Value
Foo[0]=Value(index 0 refers to p1)
CodePudding user response:
I think you need to do something like this. The code below is very generalized solution to your question and I might need some customization for yourself
using System.Reflection;
public class ReflectionBasedIndexedType
{
public int A1 { get; set; } = 10;
public int A2 { get; set; } = 20;
public string SomeString => "Hello There";
private readonly Dictionary<string, object> _underlyingCollection;
public object this[string name] => _underlyingCollection[name];
public ReflectionBasedIndexedType()
{
_underlyingCollection = GetUnderlyingCollection();
}
private Dictionary<string, object> GetUnderlyingCollection()
{
Dictionary<string, object> container = new();
// get the properties defined in the class, I am filtering
// with constraint that, I want get only public and class level
// Properties, which means I won't get any private/protected or
// static properties if there is defined such in the class
// also where filters out indexer property, which we have defined
// inside this class, without this line, there will be exception
IEnumerable<PropertyInfo> properties = GetType()
.GetProperties(BindingFlags.Instance | BindingFlags.Public)
.Where(x => x.GetIndexParameters().Length == 0);
foreach (PropertyInfo property in properties)
{
container.Add(property.Name, property.GetValue(this)!);
}
return container;
}
}
and than use case will be like this
ReflectionBasedIndexedType rbit = new();
var a1 = rbit[nameof(rbit.A1)];
var a2 = rbit[nameof(rbit.A2)];
var str = rbit[nameof(rbit.SomeString)];
Console.WriteLine(a1);
Console.WriteLine(a2);
Console.WriteLine(str);
and output in the console will be this
10
20
Hello There
CodePudding user response:
I don't know much about the database, where there might have been a ready-made solution. But at least you can do it by reflection in this way:
using System.Reflection;
[AttributeUsage(AttributeTargets.Property, Inherited = true, AllowMultiple = false)]
public sealed class IndexedPropertyAttribute : Attribute
{
readonly int index;
public IndexedPropertyAttribute(int index)
{
this.index = index;
}
public int Index
{
get { return index; }
}
}
public abstract class WithIndexedProperties
{
private Lazy<IReadOnlyDictionary<int, PropertyInfo>> properties;
protected WithIndexedProperties()
{
properties = new Lazy<IReadOnlyDictionary<int, PropertyInfo>>(
() => {
var linq = from prop in this.GetType().GetProperties()
let attr = prop.GetCustomAttributes(typeof(IndexedPropertyAttribute), true)
where attr.Length is 1
select (((IndexedPropertyAttribute)attr[0]).Index, prop);
return linq.ToDictionary(p => p.Index, p => p.prop);
});
}
public object? this[int propertyIndex]
{
get
{
return properties.Value[propertyIndex].GetValue(this);
}
set
{
properties.Value[propertyIndex].SetValue(this, value);
}
}
}
And there is an example:
Clss obj = new Clss();
obj[0] = "ABC";
obj[2] = 222;
obj[4] = 444;
// Here obj.A will be "ABC", obj.B will be 444 and obj.C will be 222.
public class Clss : WithIndexedProperties
{
[IndexedProperty(0)]
public string? A { get; init; }
[IndexedProperty(4)]
public int B { get; init; }
[IndexedProperty(2)]
public int C { get; init; }
}
CodePudding user response:
I think you have two ways at least.
The first one, is @Swapper mentioned, yo can use reflection. In this way, the class is normal and you have to write your hug code in where you want to use that class.
The second way is easier but a little fuzy. You can use dynamic
type. If you know how to use it, that's ok. Otherwise please let me know, then I will create a sample code for you.