自定义属性并在 C# 中访问它们

问题描述 投票:0回答:2

我正在开发一个将数据存储在 ConfigurationManager.AppSettings 文件中的应用程序,并且我希望以与现在不同的方式实现它。目前,我有一个接口(见下文),每个具有可保存特征的类都需要实现该接口,然后从我的 Config 类中调用静态保存方法(下面的示例)。我不喜欢我的 Config 类和具有可保存数据的类之间的耦合,因此我的理想是拥有一个指示应保存属性的属性。然后,我不会调用管理器类中的 SaveData 或 LoadData 函数,而是调用一个设置/保存所有属性的函数。这看起来与 [Serializeable] 在默认 C# 中的工作方式类似,所以我认为这是可能的。然而,我的大部分搜索都没有结果。关于如何实现这样的事情有什么想法吗?

界面

示例

c# serialization custom-attributes
2个回答
2
投票

反射就是您正在寻找的。

Reflection 提供描述程序集、模块和类型的对象(Type 类型)。您可以使用反射动态创建类型的实例、将类型绑定到现有对象,或者从现有对象获取类型并调用其方法或访问其字段和属性。如果您在代码中使用属性,反射使您能够访问它们。

假设您只对属性感兴趣,则可以使用

typeof
GetType
来获取
System.Type
的实例。然后您可以致电
GetProperties
获取
IEnumerable<PropertyInfo>
PropertyInfo
有一个
Attributes
属性,您可以使用它来检索该属性的属性。您还可以使用
PropertyInfo
的实例来检索属性的值。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

[AttributeUsage(AttributeTargets.Property)]
public class MyAttribute : Attribute
{

}

public class Foo
{
   [My]
   public string Bar { get; set; }

   public string Baz { get; set; }

   [My]
   public string Id { get; set; }
}

public static class Utilities
{
   public static IEnumerable<PropertyInfo> GetPropertiesWithMyAttribute(object obj)
   {
      return obj.GetType()
         .GetProperties(BindingFlags.Instance | BindingFlags.Public)
         .Where(pi => pi.CustomAttributes.Any(ca => ca.AttributeType == typeof(MyAttribute)));
   }
}

class Program
{
   static void Main(string[] args)
   {
      var foo = new Foo()
      {
         Bar = "Bar_Value",
         Baz = "Baz_Value",
         Id = "Id_Value"
      };

      foreach (var pi in Utilities.GetPropertiesWithMyAttribute(foo))
      {
         Console.WriteLine($"{pi.Name}: {pi.GetMethod.Invoke(foo, null).ToString()}");
      }
      foreach (var pi in Utilities.GetPropertiesWithMyAttribute(foo))
      {
         pi.SetMethod.Invoke(foo, new object[] { $"{pi.Name}_Value_Reflection" });
      }
      Console.WriteLine(foo.Bar);
      Console.WriteLine(foo.Baz);
      Console.WriteLine(foo.Id);
      Console.ReadKey();
   }
}

当然,这个例子只有

string
属性。您将必须找出某种方法来处理非字符串的属性;例如,您的示例中有一个
ObservableCollection


0
投票

只是为了选择这样做,RepoDb 实现了 IPropertyHandler 接口。

public class PersonAddressPropertyHandler : IPropertyHandler<string, Address>
{
    public Address Get(string input, PropertyHandlerGetOptions options) =>
        !string.IsNullOrEmpty(input) ? JsonConvert.Deserialize<Address>(input) : null;

    public string Set(Address input, PropertyHandlerSetOptions options) =>
        (input != null) ? JsonConvert.Serialize(input) : null;
}

在你的课堂上

public class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    [PropertyHandler(typeof(PersonAddressPropertyHandler))]
    public Address Address { get; set; }
}

一切都在文档中RepoDb

© www.soinside.com 2019 - 2024. All rights reserved.