创建挂钩到属性的getter和setter的C#属性

时间:2014-02-20 11:42:25

标签: c# attributes aop

作为我的API的一部分,我有一个抽象的BaseEntity类。我想提供一种方法以某种方式挂钩在这个类的后代中引入的新属性。我在想的是:

public class MyEntity : BaseEntity
{
    [DataElement]
    public int NewProperty { get; set; }
}

如果我可以编写一个挂在getter和setter中的属性DataElement,那么我的API将在访问时知道这个属性。

这可能吗?

UPD:我会尝试解释它的来源。我有这个BaseEntity本身没有任何数据。它的后代将声明它们可能作为属性保存的数据。我希望能够遍历对象具有的所有数据(以非常特定的形式将其存储在数据库中)。一种方法是反思。但是我想通过在访问属性时注册数据的属性来实现它。

2 个答案:

答案 0 :(得分:5)

当然,它看起来类似于以下内容:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public class DataElementAttribute : Attribute 
{ }

您必须使用反射枚举属性以查看属性是否包含该属性。 (这引出了一个问题,你真的需要这个属性吗。)

        Assembly assembly = Assembly.GetExecutingAssembly();
        foreach (Type type in assembly.GetTypes())
        {
            IList<PropertyInfo> properties = type.GetProperties();
            foreach (PropertyInfo pi in properties)
            {
                if (type.IsDefined(typeof(DataElementAttribute), false))
                {
                    // Perform Logic
                }
            }
        }

然而,将逻辑注入setter是一项不同的任务,需要在编译后完成:Why is post-compilation code injection a better idea than pre-compilation code injection?

注射MSIL并不容易。看一下这个示例代码: http://www.codeproject.com/Articles/37549/CLR-Injection-Runtime-Method-Replacer

答案 1 :(得分:1)

您可以通过添加几个抽象方法强制继承者指定如何保​​存/加载对象。

示例,受ISerializable界面的启发:

public abstract class BaseEntity
{
    public void SaveToDatabase()
    {
        var objectData = new Dictionary<string, object>();
        this.GetObjectData(objectData);
        DatabaseManager.Save(objectData);
    }

    public void LoadFromDatabase(Dictionary<string, object> data)
    {
        this.SetObjectData(data);
    }

    protected abstract void GetObjectData(Dictionary<string, object> data);

    protected abstract void SetObjectData(Dictionary<string, object> data);
}

public class MyEntity : BaseEntity
{
    public int NewProperty { get; set; }

    protected override void GetObjectData(Dictionary<string, object> data)
    {
        data.Add("NewProperty", this.NewProperty);
    }

    protected override void SetObjectData(Dictionary<string, object> data)
    {
        this.NewProperty = (int)data["NewProperty"];
    }
}