c# - 指定类型的某些属性
问题描述
我正在尝试初始化对象以进行测试。初始化对象后,我想断言其基础类型是值类型的所有属性的值都不是属性类型的默认值,但有某些例外。我不想递归到子对象。为此,我有以下内容:
public static void NoValueTypedPropertyHasDefaultValue<T>(this T t, params string[] exceptions)
where T: class
{
foreach (var property in typeof(T).GetProperties())
{
var propertyType = property.PropertyType;
if (propertyType.IsValueType && !exceptions.Any(x => x == property.Name))
{
var defaultValue = Activator.CreateInstance(propertyType);
object actualValue = property.GetValue(t);
Assert.NotEqual(defaultValue, actualValue);
}
}
}
只要一切都有一个无参数的构造函数,它就可以工作。我对为异常传递字符串的方式并不感到兴奋。有没有更好的方法来做到这一点?
解决方案
你在评论中提到:
我不高兴调用者可以只输入字符串,在这种情况下,它不会在属性重命名后继续存在。
使用System.Linq.Expressions
可以为您提供编译时安全性,允许代码如下:
var inst = new MyType { MyInt1 = 1 }; // Set MyInt1 but not MyInt2
inst.NoValueTypedPropertyHasDefaultValue(x => x.MyInt2); // Ignore MyInt2 from validation
代码如下所示(H/T从 lambda 表达式检索属性名称):
public static class Extensions
{
public static void NoValueTypedPropertyHasDefaultValue<T>(this T t, params Expression<Func<T,object>>[] propertiesToIgnore)
where T : class
{
var propertyNamesToIgnore = propertiesToIgnore.Select(x => GetMemberInfo(x).Member.Name).ToArray();
foreach (var property in typeof(T).GetProperties())
{
var propertyType = property.PropertyType;
if (propertyType.IsValueType && !propertyNamesToIgnore.Contains(property.Name))
{
var defaultValue = Activator.CreateInstance(propertyType);
object actualValue = property.GetValue(t);
Assert.NotEqual(defaultValue, actualValue);
}
}
}
private static MemberExpression GetMemberInfo(Expression method)
{
LambdaExpression lambda = method as LambdaExpression;
if (lambda == null)
throw new ArgumentNullException("method");
MemberExpression memberExpr = null;
if (lambda.Body.NodeType == ExpressionType.Convert)
{
memberExpr =
((UnaryExpression)lambda.Body).Operand as MemberExpression;
}
else if (lambda.Body.NodeType == ExpressionType.MemberAccess)
{
memberExpr = lambda.Body as MemberExpression;
}
if (memberExpr == null)
throw new ArgumentException("method");
return memberExpr;
}
}
现场示例:https ://dotnetfiddle.net/W9Q4gN (注意我已经Assert
用一个例外替换了你的调用,只是为了测试)
但是,如果所有这些对您来说看起来有点疯狂/矫枉过正(在某种程度上,确实如此!!)请记住,您可以使用nameof
原始方案。使用我的示例,您的代码将变为:
var inst = new MyType { MyInt1 = 1 }; // Set MyInt1 but not MyInt2
inst.NoValueTypedPropertyHasDefaultValue(nameof(inst.MyInt2)); // Ignore MyInt2 from validation
推荐阅读
- python - '只能将str(不是“int”)连接到str是什么意思?
- yaml - 重构 YAML 文件
- c - 如何在c中使用get()添加选项卡
- ios - Incorrect navigation bar colour in limited library picker on iOS 15
- python - 机器学习python代码优化中的新分类方法
- python - 提取 GLCM 特征
- javascript - How to emit signal in KWin scripting API
- typescript - Assign function signature to type in TypeScript
- github - 如何使用 API 在 GitHub 上为主题加注星标?
- java - Is Files.copy a thread-safe function in Java?