作为我的API的一部分,我有一个抽象的BaseEntity类。我想提供一种方法以某种方式挂钩在这个类的后代中引入的新属性。我在想的是:
public class MyEntity : BaseEntity
{
[DataElement]
public int NewProperty { get; set; }
}
如果我可以编写一个挂在getter和setter中的属性DataElement
,那么我的API将在访问时知道这个属性。
这可能吗?
UPD:我会尝试解释它的来源。我有这个BaseEntity本身没有任何数据。它的后代将声明它们可能作为属性保存的数据。我希望能够遍历对象具有的所有数据(以非常特定的形式将其存储在数据库中)。一种方法是反思。但是我想通过在访问属性时注册数据的属性来实现它。
答案 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"];
}
}