Можно ли получить значение свойства, если его прототип в интерфейсе имеет пометку атрибута?

Как можно получить значение свойства, если атрибут применен к свойству интерфейса, в то время как само свойство реализовано в классе? <br/> <br/> <pre><code class="cs">var c = new Test { Prop1 = "Hello" };
object? v = /*Здесь нужно получить значение свойства, для которого в интерфейсе назначен атрибут ITest*/ ;

[AttributeUsage(AttributeTargets.Property)]
internal sealed class TestAttribute : Attribute {}

internal interface ITest {
    [Test]
    string Ptop1 { get; set; }
}

internal sealed class Test : ITest {
    internal string Prop1 { get; set; }
}</code></pre>
  • 12 апреля 2025 г. 15:05
Ответы на вопрос 2
Чтобы получить значение свойства, помеченного атрибутом в интерфейсе, вы можете использовать механизм рефлексии в C#. В вашем примере вам нужно получить значение свойства `Prop1`, которое реализует интерфейс `ITest` с пометкой атрибута `Test`.

Для этого вам сначала нужно получить информацию об интерфейсе и атрибуте, а затем, используя рефлексию, извлечь значение свойства из экземпляра класса. Вот пример кода, который демонстрирует, как это сделать:

```csharp
using System;
using System.Linq;
using System.Reflection;

[AttributeUsage(AttributeTargets.Property)]
internal sealed class TestAttribute : Attribute {}

internal interface ITest {
    [Test]
    string Prop1 { get; set; }
}

internal sealed class Test : ITest {
    internal string Prop1 { get; set; }
}

class Program {
    static void Main() {
        var c = new Test { Prop1 = "Hello" };

        // Получаем тип интерфейса
        var interfaceType = typeof(ITest);
        
        // Получаем все свойства интерфейса
        var properties = interfaceType.GetProperties(BindingFlags.Public | BindingFlags.Instance);

        foreach (var property in properties) {
            // Проверяем наличие атрибута Test
            var hasAttribute = property.GetCustomAttributes(typeof(TestAttribute), false).Any();
            if (hasAttribute) {
                // Если атрибут есть, получаем значение из класса Test
                var value = property.GetValue(c);
                Console.WriteLine(value); // Вывод: Hello
            }
        }
    }
}
```

### Объяснение кода:
1. **AttributeUsage**: Определяет атрибут `TestAttribute`, который вы используете для пометки свойства.
2. **ITest Interface**: Это ваш интерфейс с свойством `Prop1`, художественно помеченным атрибутом `Test`.
3. **Test Class**: Класс `Test` реализует интерфейс `ITest` и определяет внутреннее свойство `Prop1`.
4. **Рефлексия**:
   - Получает тип интерфейса с помощью `typeof(ITest)`.
   - Получает все публичные свойства интерфейса через `GetProperties`.
   - Проверяет, есть ли атрибут `Test` у каждого свойства.
   - Если атрибут присутствует, извлекается значение свойства с использованием `GetValue`.

Запустив этот код, вы получите значение свойства `Prop1`, равное "Hello".
using System.Reflection;

namespace ConsoleAppTest
{
    public static class Program
    {
        private static void Main(string[] args)
        {
            Test obj = new() { Prop1 = "Prop1 Value" };
            // Получаем тип объекта
            Type objType = typeof(Test);
            // Получаем список интерфейсов
            Type[] interfaces = objType.GetInterfaces();
            foreach (Type iface in interfaces)
            {
                // Получаем список свойств интерфейса
                PropertyInfo[] ifaceProperties = iface.GetProperties();
                foreach (PropertyInfo prop in ifaceProperties)
                {
                    // Ищем нужный аттрибут в свойстве
                    Attribute? attribute = prop.GetCustomAttribute<TestAttribute>();
                    if (attribute != null)
                    {
                        // Получаем значение свойства
                        object? propValue = prop.GetValue(obj); // -> Prop1 Value
                    }
                }
            }
        }
    }
    
    [AttributeUsage(AttributeTargets.Property)]
    public sealed class TestAttribute : Attribute
    { }

    internal sealed class Test : ITest
    {
        public string Prop1 { get; set; } = string.Empty;
    }

    internal interface ITest
    {
        [Test]
        public string Prop1 { get; set; }
    }
}
Похожие вопросы