我们可以使用c#索引器来索引类属性吗



我想像数组一样索引类属性。

Public class Foo
{
propery p1{get;set;}
propery p3{get;set;}
propery p3{get;set;}
.
.
.
.

}

我想像数组一样索引每个属性FOO.p1=值

Foo[0]=值(索引0表示p1(

我对数据库了解不多,那里可能有现成的解决方案。但至少你可以通过这种方式进行反思:

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

还有一个例子:

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

我认为您需要这样做。下面的代码是你的问题的通用解决方案,我可能需要为自己定制

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

而用例将像这个

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

控制台中的输出将是这个

10
20
Hello There

我认为您至少有两种方法。第一个,是@Swapper提到的,你可以使用反射。通过这种方式,类是正常的,您必须在想要使用该类的地方编写拥抱代码。第二种方法比较简单,但有点模糊。您可以使用dynamic类型。如果你知道如何使用它,那没关系。否则请告诉我,然后我会为你创建一个示例代码。

最新更新