C# 获取多个属性的名称/值
假设我有一个方法,提取属性名称和值:C# 获取多个属性的名称/值,c#,.net,dapper,C#,.net,Dapper,假设我有一个方法,提取属性名称和值: public TModel Get (Expression<Func<object>> param) { using (OracleConnection connection = new OracleConnection(GetConnectionString())) { connection.Open(); var propertyName= ((Me
public TModel Get (Expression<Func<object>> param)
{
using (OracleConnection connection = new OracleConnection(GetConnectionString()))
{
connection.Open();
var propertyName= ((MemberExpression)param.Body).Member.Name;
var value = param.Compile()();
// GetTableName() returns table name of TModel
var query = $"SELECT * FROM {GetTableName()} WHERE {propertyName}='{value}'";
var output = connection.Query<TModel>(query);
connection.Dispose();
return output.FirstOrDefault();
}
}
但是,如果我想从未知数量的属性中获取名称和值,我会执行以下操作:
public TModel Get(params Expression<Func<object>>[] param)
using (OracleConnection connection = new OracleConnection(GetConnectionString()))
{
connection.Open();
var query = new StringBuilder();
query.Append($"SELECT * FROM {GetTableName()} WHERE ");
for (int i = 0; i < param.Length; i++)
{
var propertyName = ((MemberExpression)param[i].Body).Member.Name;
var value = param[i].Compile()();
query.Append($"{propertyName} = '{value}'");
if (i + 1 < param.Length) query.Append(" AND ");
}
var output = connection.Query<TModel>(query.ToString());
connection.Dispose();
return output.FirstOrDefault();
}
}
我可以手动发送属性名+值,但是,我希望实现尽可能简单,不太冗长
有什么方法可以简化这一点吗?我们可以通过使Get泛型、提供Get foo实例并将表达式更改为T、object来缩短表达式,以便它们可以接受foo
using System;
using System.Linq.Expressions;
namespace SO60378405
{
static class Program
{
static void Main(string[] args)
{
var foo = new SomeContainer("hello", 123);
Get(foo, s => s.SomeString, s => s.SomeInt);
}
static void Get<T>(T foo, params Expression<Func<T, object>>[] expressions)
{
foreach (var expression in expressions)
{
var memberExpression = GetMemberExpression(expression);
var propertyName = memberExpression.Member.Name;
var propertyGetter = expression.Compile();
var propertyValue = propertyGetter(foo);
Console.WriteLine($"{propertyName} = '{propertyValue}'");
}
}
static MemberExpression GetMemberExpression<T>(Expression<Func<T, object>> expression)
{
switch (expression.Body)
{
case MemberExpression memberExpression:
return memberExpression; //string
case UnaryExpression unaryExpression when unaryExpression.Operand is MemberExpression operandMemberExpression:
return operandMemberExpression; //int, decimal
default:
throw new InvalidOperationException();
}
}
}
public class SomeContainer
{
public string SomeString { get; set; }
public int SomeInt { get; set; }
public SomeContainer(string someString, int someInt)
{
SomeString = someString;
SomeInt = someInt;
}
}
}
使用系统;
使用System.Linq.Expressions;
名称空间SO60378405
{
静态类程序
{
静态void Main(字符串[]参数)
{
var foo=newsomecontainer(“hello”,123);
Get(foo,s=>s.SomeString,s=>s.SomeInt);
}
静态void Get(T foo,参数表达式[]表达式)
{
foreach(表达式中的var表达式)
{
var memberExpression=GetMemberExpression(表达式);
var propertyName=memberExpression.Member.Name;
var propertyGetter=expression.Compile();
var propertyValue=propertyGetter(foo);
WriteLine($“{propertyName}='{propertyValue}'”;
}
}
静态MemberExpression GetMemberExpression(表达式)
{
开关(expression.Body)
{
案例成员表达式成员表达式:
返回memberExpression;//字符串
大小写一元表达式一元表达式当一元表达式。操作数为MemberExpression操作数MemberExpression时:
返回操作数MemberExpression;//整数,十进制
违约:
抛出新的InvalidOperationException();
}
}
}
公共类容器
{
公共字符串SomeString{get;set;}
公共int SomeInt{get;set;}
公共SomeContainer(string-someString,int-someInt)
{
SomeString=SomeString;
SomeInt=SomeInt;
}
}
}
如果这是您编写的代码,并且它可以正常工作,并且您希望对代码的各个方面进行审查,那么这可能会更好,但我会在询问之前先查看他们的帮助中心。您这样做是出于速度原因吗?反射已经有了这个功能。@RobertHarvey我这样做是因为我使用的是Oracle数据库和Dapper。但是,Dapper.contrib对oracle不是很友好,我不想手动编写每个查询。因此,我想出了一个想法,有一个方法可以基于给定的属性构建该查询。我的代码片段可以工作,但是,正如我所提到的,它看起来有点“冗长”,特别是对于3+参数,每次我通过属性时都会强制写入“()=>”。我想我们必须看到更多的代码才能找到解决方案。@RobertHarvey我编辑了我的帖子。
var model = Get(() => foo.FirstProperty, () => foo.SecondProperty); // and so on
using System;
using System.Linq.Expressions;
namespace SO60378405
{
static class Program
{
static void Main(string[] args)
{
var foo = new SomeContainer("hello", 123);
Get(foo, s => s.SomeString, s => s.SomeInt);
}
static void Get<T>(T foo, params Expression<Func<T, object>>[] expressions)
{
foreach (var expression in expressions)
{
var memberExpression = GetMemberExpression(expression);
var propertyName = memberExpression.Member.Name;
var propertyGetter = expression.Compile();
var propertyValue = propertyGetter(foo);
Console.WriteLine($"{propertyName} = '{propertyValue}'");
}
}
static MemberExpression GetMemberExpression<T>(Expression<Func<T, object>> expression)
{
switch (expression.Body)
{
case MemberExpression memberExpression:
return memberExpression; //string
case UnaryExpression unaryExpression when unaryExpression.Operand is MemberExpression operandMemberExpression:
return operandMemberExpression; //int, decimal
default:
throw new InvalidOperationException();
}
}
}
public class SomeContainer
{
public string SomeString { get; set; }
public int SomeInt { get; set; }
public SomeContainer(string someString, int someInt)
{
SomeString = someString;
SomeInt = someInt;
}
}
}