相关疑难解决方法(0)

为什么要使用Expression <Func <T >>而不是Func <T>?

我理解lambdas FuncAction代表们.但表达方式让我很难过.在什么情况下你会使用一个Expression<Func<T>>而不是一个普通的老年人Func<T>

c# lambda delegates expression-trees

910
推荐指数
10
解决办法
21万
查看次数

从lambda表达式中检索属性名称

通过lambda表达式传入时,是否有更好的方法来获取属性名称?这是我现在拥有的.

例如.

GetSortingInfo<User>(u => u.UserId);
Run Code Online (Sandbox Code Playgroud)

只有当属性是字符串时,它才能将其作为元素表达式进行处理.因为不是所有属性都是字符串我必须使用对象,但它会返回一个单一表达式.

public static RouteValueDictionary GetInfo<T>(this HtmlHelper html, 
    Expression<Func<T, object>> action) where T : class
{
    var expression = GetMemberInfo(action);
    string name = expression.Member.Name;

    return GetInfo(html, name);
}

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 …
Run Code Online (Sandbox Code Playgroud)

c# linq lambda expression-trees

489
推荐指数
14
解决办法
21万
查看次数

获取属性的名称作为字符串

(参见下面我使用我接受的答案创建的解决方案)

我正在尝试提高一些涉及反射的代码的可维护性.该应用程序有一个.NET Remoting接口,公开(除此之外)一个名为Execute的方法,用于访问未包含在其已发布的远程接口中的应用程序部分.

以下是应用程序如何指定可通过Execute访问的属性(本例中为静态属性):

RemoteMgr.ExposeProperty("SomeSecret", typeof(SomeClass), "SomeProperty");
Run Code Online (Sandbox Code Playgroud)

所以远程用户可以调用:

string response = remoteObject.Execute("SomeSecret");
Run Code Online (Sandbox Code Playgroud)

并且应用程序将使用反射来查找SomeClass.SomeProperty并将其值作为字符串返回.

不幸的是,如果有人重命名SomeProperty并忘记更改ExposeProperty()的第3个parm,它会破坏这种机制.

我需要相当于:

SomeClass.SomeProperty.GetTheNameOfThisPropertyAsAString()
Run Code Online (Sandbox Code Playgroud)

在ExposeProperty中用作第三个parm,因此重构工具将负责重命名.

有没有办法做到这一点?提前致谢.

好的,这是我最终创建的内容(根据我选择的答案和他引用的问题):

// <summary>
// Get the name of a static or instance property from a property access lambda.
// </summary>
// <typeparam name="T">Type of the property</typeparam>
// <param name="propertyLambda">lambda expression of the form: '() => Class.Property' or '() => object.Property'</param>
// <returns>The name of the property</returns>
public string GetPropertyName<T>(Expression<Func<T>> propertyLambda)
{
    var me = propertyLambda.Body as MemberExpression;

    if (me == null)
    { …
Run Code Online (Sandbox Code Playgroud)

c# reflection properties

191
推荐指数
9
解决办法
20万
查看次数

将.net Func <T>转换为.net Expression <Func <T >>

使用方法调用很容易从lambda转到Expression

public void GimmeExpression(Expression<Func<T>> expression)
{
    ((MemberExpression)expression.Body).Member.Name; // "DoStuff"
}

public void SomewhereElse()
{
    GimmeExpression(() => thing.DoStuff());
}
Run Code Online (Sandbox Code Playgroud)

但我想将Func转换为表达式,仅在极少数情况下......

public void ContainTheDanger(Func<T> dangerousCall)
{
    try 
    {
        dangerousCall();
    }
    catch (Exception e)
    {
        // This next line does not work...
        Expression<Func<T>> DangerousExpression = dangerousCall;
        var nameOfDanger = 
            ((MemberExpression)dangerousCall.Body).Member.Name;
        throw new DangerContainer(
            "Danger manifested while " + nameOfDanger, e);
    }
}

public void SomewhereElse()
{
    ContainTheDanger(() => thing.CrossTheStreams());
}
Run Code Online (Sandbox Code Playgroud)

不起作用的行给了我编译时错误Cannot implicitly convert type 'System.Func<T>' to 'System.Linq.Expressions.Expression<System.Func<T>>'.显式强制转换无法解决问题.我有一个设施可以做到这一点吗?

.net c# lambda expression func

113
推荐指数
7
解决办法
6万
查看次数

C#:从lambda表达式中获取链中属性的名称

我正在开发一个使用lambda表达式来指定属性的API.我正在使用这个与此类似的着名代码(这是简化和不完整的,只是为了说清楚我在说什么):

public void Foo<T, P>(Expression<Func<T, P>> action)
{
    var expression = (MemberExpression)action.Body;
    string propertyName = expression.Member.Name;
    // ...
}
Run Code Online (Sandbox Code Playgroud)

被称为这样:

Foo((String x) => x.Length);
Run Code Online (Sandbox Code Playgroud)

现在我想通过链接属性名来指定属性路径,如下所示:

Foo((MyClass x) => x.Name.Length);
Run Code Online (Sandbox Code Playgroud)

Foo应该能够将路径拆分为其属性名称("Name""Length").有没有办法以合理的努力做到这一点?


有一个类似的外观问题,但我认为他们正试图在那里结合lambda表达式.

另一个问题也是处理嵌套的属性名称,但我真的不明白他们在谈论什么.

c# lambda

37
推荐指数
3
解决办法
8796
查看次数

给定一个Member Access lambda表达式,将其转换为具有完全访问路径的特定字符串表示

鉴于

Expression<Func<T, object>> 
Run Code Online (Sandbox Code Playgroud)

(例如x => x.Prop1.SubProp),我想根据需要创建一个字符串"Prop1.SubProp".

在单次访问的情况下(例如x => x.Prop1),我可以轻松地执行以下操作:

MemberExpression body = (expression.Body.NodeType == ExpressionType.Convert) ? (MemberExpression)((UnaryExpression)expression.Body).Operand : (MemberExpression)expression.Body;
return body.Member.Name;
Run Code Online (Sandbox Code Playgroud)

但是,如果存在更深的嵌套,例如x => x.Prop1.SubProp1,则只获得嵌套最深的名称,例如"SubProp1"而不是"Prop1.SubProp1"

反正有没有访问lambda表达式的完整属性路径?

.net c# linq

29
推荐指数
2
解决办法
1万
查看次数

在C#中编译时间反射

我经常编写C#代码,必须使用魔术字符串来表达属性名称.每个人都知道魔术弦的问题.它们很难重构,它们没有编译时检查,并且通常会导致难以诊断的问题.然而,C#/ .NET 在整个地方使用它们来表示属性/类/方法名称.

这个问题已持续多年和多年,目前唯一可行的解​​决方案是使用表达式树,然后在运行时解析属性名称.这使您获得令人满意的编译时检查,但它使代码复杂化(需要Expression类型的参数),并且会产生运行时成本.

有没有人知道是否有一个特性考虑因为C#/ .NET添加编译时反射来克服这个普遍存在的问题?

看起来这将是一个简单的补充,它将是一个非破坏性的变化,它将使许多开发人员受益匪浅.typeof()运算符已经执行了编译时反射的形式,因此看起来运算符nameof()(或类似的东西)将非常互补.

此外,有没有人知道这个功能的任何潜在问题?

谢谢您的帮助.

.net c# strong-typing compile-time magic-string

22
推荐指数
3
解决办法
9561
查看次数

获取.NET 3.5中的Lambda表达式中使用的属性名称

我有一个问题,一直困扰我一段时间,我找不到答案.

我需要获取Lambda表达式中引用的属性的名称.我会将lambda表达式提供给一个返回字符串的方法.例如,如果我有:

x => x.WeirdPropertyName
Run Code Online (Sandbox Code Playgroud)

然后该方法将返回:

"WeirdPropertyName"
Run Code Online (Sandbox Code Playgroud)

我已经读过它可以用表达式树来完成,但答案已经没有了.

谢谢你的帮助

.net c# lambda

17
推荐指数
2
解决办法
8369
查看次数

从表达式获取字符串属性名称

我正在尝试写一个强类型帮助器,它将是这样的:

Html.Lookup(x => x.FooId);
Run Code Online (Sandbox Code Playgroud)

现在我有这个:

public static MvcHtmlString Lookup<T,TReturn>(this HtmlHelper<T> html, Func<T, TReturn> expression)
{
     // get string "FooId" here
}
Run Code Online (Sandbox Code Playgroud)

谁知道怎么弄这个?

.net c# asp.net-mvc lambda

11
推荐指数
3
解决办法
1万
查看次数

ExpressionHelper.GetExpressionText(表达式)不返回我的属性的名称

我已经实现了一个MVC扩展来格式化我的应用程序中的数字.它基于此处的代码.如下

public static MvcHtmlString DecimalBoxFor<TModel>(this HtmlHelper<TModel> html, Expression<Func<TModel, double?>> expression, string format, object htmlAttributes = null)
{
    var name = ExpressionHelper.GetExpressionText(expression);   
    double? dec = expression.Compile().Invoke(html.ViewData.Model);
    var value = dec.HasValue ? (!string.IsNullOrEmpty(format) ? dec.Value.ToString(format) : dec.Value.ToString()): "";
    return html.TextBox(name, value, htmlAttributes);
}
Run Code Online (Sandbox Code Playgroud)

当我使用以下Razor语法行调用它时

@Html.DecimalBoxFor(model => Model.PointAttributes[i].Data.Y,"0.000", new { @class = "span1 number" })
Run Code Online (Sandbox Code Playgroud)

我得到一个例外,因为我的扩展名中的变量'name'是一个空字符串.我已经尝试将var name行更改为this但它只给了我'Y'的属性名称,而不是我需要将模型绑定回MVC的完整'Model.PointAttributes [i] .Data.Y'.

var name = ((expression.Body is MemberExpression ?((MemberExpression)expression.Body).Member : ((MemberExpression)((UnaryExpression)expression.Body).Operand).Member)).Name;
Run Code Online (Sandbox Code Playgroud)

lambda asp.net-mvc-3

6
推荐指数
2
解决办法
3222
查看次数

将Lambda表达式树转换预编译为常量?

取一个Expression树并将其转换为其他形式(例如字符串表示形式)是很常见的(例如,这个问题这个问题,我怀疑Linq2Sql做类似的事情)。

在很多情况下,即使在大多数情况下,表达式树的转换也总是相同的,即如果我有一个函数

public string GenerateSomeSql(Expression<Func<TResult, TProperty>> expression)
Run Code Online (Sandbox Code Playgroud)

那么具有相同参数的任何调用将始终返回相同的结果,例如:

GenerateSomeSql(x => x.Age)  //suppose this will always return "select Age from Person"
GenerateSomeSql(x => x.Ssn)  //suppose this will always return "select Ssn from Person"
Run Code Online (Sandbox Code Playgroud)

因此,从本质上讲,带有特定参数的函数调用实际上只是一个常量,除了在运行时不断地重新计算时间而浪费时间之外。

出于争论的原因,假定转换足够复杂以至于引起明显的性能下降,是否有任何方法可以将函数调用预编译为实际常量?

编辑 似乎没有办法在C#本身中完全做到这一点。您可能会在c#中找到最接近的一个答案(当然,尽管您要确保缓存本身不比重新生成慢)。要真正转换为真正的常数,我怀疑经过一些工作,您可以在编译后使用诸如mono-cecil之类的方法来修改字节码。

.net c# linq

5
推荐指数
1
解决办法
898
查看次数

具有动作/条件的属性

是否可以指定实现以下内容:

[SomeAttribute(condition1)]
public SomeType SomeSetting1 {get; set;}

[SomeAttribute(condition2)]
public SomeType SomeSetting2 {get; set;}
Run Code Online (Sandbox Code Playgroud)

那里的条件是什么复杂的?举个例子,

[SomeAttribute(SomeSetting3 == 4 && SomeSetting4 < 100)]
Run Code Online (Sandbox Code Playgroud)

PropertyGrid用来显示/编辑配置作为某些可序列化类的属性.我需要进行一些级联:当设置某些设置时,其他一些设置可能会被隐藏,具体取决于值.

目前,我可以通过这种方式隐藏一些设置:

  • 创建新属性,基于 IHide
  • 将其分配给所需的属性
  • 检查给定属性的所有属性ConfigWrapper,如果有任何IHide类型,则检查它Hide以决定何时show(添加到属性的结果集合).

    public interface IHide
    {
        bool Hide { get; }
    }
    
    public class AdminAttribute : Attribute, Common.IHide
    {
        public bool Hide
        {
            get { return !MySettings.Admin; }
        }
    
        public override object TypeId { get { return "AdminAttributeId"; } }
    } …
    Run Code Online (Sandbox Code Playgroud)

c# propertygrid attributes properties

5
推荐指数
2
解决办法
3357
查看次数