我有一个功能,可以根据字符串输入查找字段。我想检查该字段是否不为空,如果不为空,则返回该行。示例代码显示了硬编码的else-if语句(实际上更长一些)。我想知道是否有更简单的方法可以做到这一点。我的直觉说反射,但是我不知道该怎么做,或者不知道该怎么搜索。
public class Spell
{
public string name { get; set; }
public string description { get; set; }
public string sor { get; set; }
public string wiz { get; set; }
public string cleric { get; set; }
}
public IEnumerable<Spell> GetSpellsForClass(string classname)
{
if(classname =="sor")
return _context.Spells.Where(x=> !string.IsNullOrEmpty(x.sor));
else if (classname == "wiz")
return _context.Spells.Where(x => !string.IsNullOrEmpty(x.wiz));
else if(classname == "cleric")
return _context.Spells.Where(x => !string.IsNullOrEmpty(x.cleric));
}
我希望输入'sor','wiz'或'cleric',并希望函数搜索相应的字段,检查其是否为空,然后返回整个对象。
答案 0 :(得分:0)
您可以这样:
_context.Spells.Where(s => typeof(Spell).GetProperty(classname).GetValue(s) != null);
这样,您只需搜索类名(我建议使用propertyName代替变量名),而没有if else语句。
答案 1 :(得分:0)
将字典用于咒语类型是否更清洁?您可以拥有与拼写或某些不同标记相关的类的表。然后,您可以在类中拥有属性-假设您可以访问的CharacterClasses列表 ID。通过消除反射,这也可以提高您的性能。
答案 2 :(得分:0)
我认为您能做的最好是使用stmt->execute();
将类名映射到访问相应成员的lambda方法。这将不如您的Dictionary
/ if
方法(或更有效的是else
/ switch
)方法有效。注意:如果您的case
足够长,则编译器可能会生成一个案例哈希表以查找分支的位置。
提醒我们这是一个LINQ to EF查询,我已更新以构建适当的switch
。
给出:
Expression
还有一个Dictionary<string, Expression<Func<Spell, string>>> AccessSpellClass = new Dictionary<string, Expression<Func<Spell, string>>>() {
{ "sor", s => s.sor },
{ "wiz", s => s.wiz },
{ "cleric", s => s.cleric },
};
用于替换ExpressionVisitor
:
Expression
您可以在您的方法中使用它:
public static class ExpressionExt {
/// <summary>
/// Replaces an Expression (reference Equals) with another Expression
/// </summary>
/// <param name="orig">The original Expression.</param>
/// <param name="from">The from Expression.</param>
/// <param name="to">The to Expression.</param>
/// <returns>Expression with all occurrences of from replaced with to</returns>
public static Expression Replace(this Expression orig, Expression from, Expression to) => new ReplaceVisitor(from, to).Visit(orig);
}
/// <summary>
/// ExpressionVisitor to replace an Expression (that is Equals) with another Expression.
/// </summary>
public class ReplaceVisitor : ExpressionVisitor {
readonly Expression from;
readonly Expression to;
public ReplaceVisitor(Expression from, Expression to) {
this.from = from;
this.to = to;
}
public override Expression Visit(Expression node) => node == from ? to : base.Visit(node);
}
最好创建一个public IEnumerable<Spell> GetSpellsForClass(string classname) {
if (AccessSpellClass.TryGetValue(classname, out var accessExpr)) {
Expression<Func<string,bool>> testExpr = x => !String.IsNullOrEmpty(x);
var newTestBody = testExpr.Body.Replace(testExpr.Parameters[0], accessExpr.Body);
var newTestExpr = Expression.Lambda<Func<Spell,bool>>(newTestBody, accessExpr.Parameters[0]);
return _context.Spells.Where(newTestExpr);
}
else
return Enumerable.Empty<Spell>();
}
,然后在程序开始时在运行时构建Attribute
:
Dictionary
注意:如果不能使用自定义属性,则可以修改该方法以获取属性名称列表,并为这些属性构建字典条目。
答案 3 :(得分:-1)
这是使用扩展方法的基于反射的答案,我想这是您真正想要的。
public static bool TryIsPropertyNull(this object obj, string PropName, out bool isNull)
{
isNull = false;
var prop = obj.GetType().GetProperty(PropName);
if (prop == null)
return false;
isNull = prop.GetValue(obj) == null;
return true;
}
我这样做是为了“尝试”解决属性名称不存在的情况。 希望这可以为您提供正确方向的一些指示