簡體   English   中英

我們可以使用 c# 索引器來索引 class 屬性嗎?

[英]Can we use c# indexer to index class properties?

我想像數組一樣索引 class 屬性。

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

propery p3{get;set;}
propery p3{get;set;}
.
.
.
.



}

我想像數組 FOO.p1=Value 一樣索引每個屬性

Foo[0]=Value(索引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);

控制台中的 output 就是這個

10
20
Hello There

我認為你至少有兩種方法。 第一個,是@Swapper提到的,你可以使用反射。 這樣,class就正常了,你必須在你想使用class的地方寫你的擁抱代碼。第二種方式更簡單,但有點模糊。 您可以使用dynamic類型。 如果您知道如何使用它,那沒關系。 否則請告訴我,然后我將為您創建示例代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM