- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我们有一个 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 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/
你能比较一下属性吗 我想禁用文本框“txtName”。有两种方式 使用javascript,txtName.disabled = true 使用 ASP.NET, 哪种方法更好,为什么? 最佳答案 我
Count 属性 返回一个集合或 Dictionary 对象包含的项目数。只读。 object.Count object 可以是“应用于”列表中列出的任何集合或对
CompareMode 属性 设置并返回在 Dictionary 对象中比较字符串关键字的比较模式。 object.CompareMode[ = compare] 参数
Column 属性 只读属性,返回 TextStream 文件中当前字符位置的列号。 object.Column object 通常是 TextStream 对象的名称。
AvailableSpace 属性 返回指定的驱动器或网络共享对于用户的可用空间大小。 object.AvailableSpace object 应为 Drive 
Attributes 属性 设置或返回文件或文件夹的属性。可读写或只读(与属性有关)。 object.Attributes [= newattributes] 参数 object
AtEndOfStream 属性 如果文件指针位于 TextStream 文件末,则返回 True;否则如果不为只读则返回 False。 object.A
AtEndOfLine 属性 TextStream 文件中,如果文件指针指向行末标记,就返回 True;否则如果不是只读则返回 False。 object.AtEn
RootFolder 属性 返回一个 Folder 对象,表示指定驱动器的根文件夹。只读。 object.RootFolder object 应为 Dr
Path 属性 返回指定文件、文件夹或驱动器的路径。 object.Path object 应为 File、Folder 或 Drive 对象的名称。 说明 对于驱动器,路径不包含根目录。
ParentFolder 属性 返回指定文件或文件夹的父文件夹。只读。 object.ParentFolder object 应为 File 或 Folder 对象的名称。 说明 以下代码
Name 属性 设置或返回指定的文件或文件夹的名称。可读写。 object.Name [= newname] 参数 object 必选项。应为 File 或&
Line 属性 只读属性,返回 TextStream 文件中的当前行号。 object.Line object 通常是 TextStream 对象的名称。 说明 文件刚
Key 属性 在 Dictionary 对象中设置 key。 object.Key(key) = newkey 参数 object 必选项。通常是 Dictionary 
Item 属性 设置或返回 Dictionary 对象中指定的 key 对应的 item,或返回集合中基于指定的 key 的&
IsRootFolder 属性 如果指定的文件夹是根文件夹,返回 True;否则返回 False。 object.IsRootFolder object 应为&n
IsReady 属性 如果指定的驱动器就绪,返回 True;否则返回 False。 object.IsReady object 应为 Drive&nbs
FreeSpace 属性 返回指定的驱动器或网络共享对于用户的可用空间大小。只读。 object.FreeSpace object 应为 Drive 对象的名称。
FileSystem 属性 返回指定的驱动器使用的文件系统的类型。 object.FileSystem object 应为 Drive 对象的名称。 说明 可
Files 属性 返回由指定文件夹中所有 File 对象(包括隐藏文件和系统文件)组成的 Files 集合。 object.Files object&n
我是一名优秀的程序员,十分优秀!