gpt4 book ai didi

c# - 获取派生类属性的属性或名称

转载 作者:太空狗 更新时间:2023-10-30 01:29:30 24 4
gpt4 key购买 nike

我们有一个 BaseClass和一组派生的 POCO 类(参见 DerivedClassA )。它们映射到数据库中我们目前无法更改的现有键值存储。

派生类的每个属性都将映射到商店中的一个键。属性表示的键是字符串值,它们可以是属性名称或(如果存在)自定义属性 MyAttribute.KeyPropertyC 所示以下。该属性的常见用例是如果键以整数开头,这对 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 Answers 中挖掘之后(我没有声称任何级别的泛型专业知识),我们想出了 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()进入非泛型BaseClass , 它不再有 T派生类的类型,它需要查找派生类的属性集。我不想添加重复项 GetKey() s 在每个派生类中。

问题:

有没有办法移动 GetKey()方法(可能重写)到 BaseClass而不是引入新的 BaseClass<T>仅支持GetKey()

其他背景:

我们正在尝试将面向对象/强类型包装在一个数据存储周围,该数据存储只是一个看起来像这样的表:

| PreferenceId | UserId | PreferenceString |

每个派生类代表一个不同的PreferenceId .每个PreferenceString只是一串键/值以自定义的方式“序列化”PreferenceId (所有 PreferenceIds 之间没有可以共享的押韵/原因)。这一切都应该在某个时候重新设计,但我们正在尝试将当前商店包装在某种强类型中,作为过渡的一个步骤。

最佳答案

对我来说,所有这些结构总体上似乎很疯狂而且过于复杂。
考虑重写整个方法而不是更改 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);

关于c# - 获取派生类属性的属性或名称,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51540318/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com