为了账号安全,请及时绑定邮箱和手机立即绑定

获取派生类属性的属性或名称

获取派生类属性的属性或名称

C#
婷婷同学_ 2021-10-31 19:41:45
我们有一个BaseClass和一组派生的 POCO 类(参见 参考资料DerivedClassA)。它们映射到数据库中我们目前无法更改的现有键值存储。派生类上的每个属性都将映射到存储中的一个键。属性表示的键是字符串值,它们是属性名称或(如果存在)自定义属性MyAttribute.Key,PropertyC如下所示。属性的常见用例是如果键以整数开头,这对于 C# 属性名称无效(并且我们无法更改键)。public class BaseClass{    public int BaseClass Id { get; set; } = 0;}public class DerivedClassA : BaseClass{    public int PropertyA { get; set; }    public int PropertyB { get; set; }    [MyAttribute(Key = "404Property")]    public int PropertyC { get; set; }}在代码中,我们需要以字符串的形式获取键值。在从其他 SO 答案中进行了一些摔跤和挖掘之后(我不声称对泛型具有任何专业水平),我们想出了下面GetKey()派生的方法BaseClass<T>。请注意,这GetCustomAttributeValue<T>()是一个返回属性值的自定义帮助器方法(可能有更好的方法来做到这一点,但这超出了本问题的范围)。public class BaseClass<T> : BaseClass where T : BaseClass<T>{    public string GetKey(Expression<Func<T, object>> property)    {        var memberInfo = GetMemberInfo(property);        return GetAttributeKey(memberInfo) ?? memberInfo?.Name;    }    private static MemberInfo GetMemberInfo(Expression<Func<T, object>> property) =>        (property.Body as MemberExpression ?? ((UnaryExpression)property.Body).Operand as MemberExpression)?.Member;    private static string GetAttributeKey(MemberInfo member) =>        member.GetCustomAttributeValue<string>(typeof(MyAttribute), "Key");}如果我们从新的类派生类,这个解决方案似乎有效 BaseClass<T>    public class DerivedClassA : BaseClass<T> {        ...    }在GetKey()现在被称为如下:var derivedClassA = new DerivedClassA();var propertyCKey = derivedClassA.GetKey(p => p.PropertyC);BaseClass然而,我们有一个需要保留的需求,我们不希望BaseClass.当我尝试GetKey()进入 non-generic 时BaseClass,它不再具有T派生类的类型,它需要在派生类上查找属性集。我不想GetKey()在每个派生类中添加重复的s。题:有没有办法将GetKey()方法(可能重写它)移入BaseClass而不是引入新的BaseClass<T>仅用于支持GetKey()?附加背景:我们试图将面向对象/强类型包装在一个数据存储周围,该数据存储只是一个看起来像这样的表:| PreferenceId | UserId | PreferenceString |每个派生类代表一个不同的PreferenceId. 每个PreferenceString都只是一串以自定义方式“序列化”的键/值PreferenceId(没有可以在所有人之间共享的韵律/原因PreferenceIds)。这一切都应该在某个时候重新设计,但我们正在尝试将当前商店包装在某种强类型中,作为过渡的一个步骤。
查看完整描述

1 回答

?
慕丝7291255

TA贡献1859条经验 获得超6个赞

对我而言,所有这些结构总体上似乎很疯狂且过于复杂。

考虑重写整个方法而不是改变GetKey方法。


一般来说,GetKey在你的基类中打破单一职责原则。


如果我必须这样做,我会把这个功能提取到一个静态类中:


public static class CustomKeysHelper

{

    public static string GetKey<T>(Expression<Func<T, object>> property) where T : BaseClass

    {

        var memberInfo = GetMemberInfo(property);

        return GetAttributeKey(memberInfo) ?? memberInfo?.Name;

    }


    private static MemberInfo GetMemberInfo<T>(Expression<Func<T, object>> property) =>

        (property.Body as MemberExpression ?? ((UnaryExpression)property.Body).Operand as MemberExpression)?.Member;


    private static string GetAttributeKey<T>(MemberInfo member) =>

        member.GetCustomAttributeValue<string>(typeof(MyAttribute), "Key");

}


// Usage:

string cKey = CustomKeysHelper.GetKey<DerivedClassA>(dca => dca.PropertyC);

是的,它让每次GetKey调用看起来更长,但它分离了这个逻辑并使你的意图清晰。


万一您有对象的实例BaseClass并想从实例中提取属性名称,而不是类型,那么您可以使用扩展方法:


public static class CustomKeysHelper

{

    // ... see above


    public static string GetKey<T>(this T obj, Expression<Func<T, object>> property) where T : BaseClass

    {

        return GetKey<T>(property);

    }

}    


// Now, you can do this:

DerivedClassA derAInstance = ...;

derAInstance.GetKey(dca => dca.PropertyC);


查看完整回答
反对 回复 2021-10-31
  • 1 回答
  • 0 关注
  • 216 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信