gpt4 book ai didi

c# - 使用 Lambda 的属性构造函数

转载 作者:可可西里 更新时间:2023-11-01 09:09:06 27 4
gpt4 key购买 nike

有可能这样做:

public static void SomeMethod<TFunc>(Expression<TFunc> expr)
{
//LambdaExpression happily excepts any Expession<TFunc>
LambdaExpression lamb = expr;
}

并在别处调用它,为参数传递一个 lambda:

SomeMethod<Func<IQueryable<Person>,Person>>( p=>p.FirstOrDefault());

我想将表达式作为参数传递给属性构造函数是否可以执行以下操作?

class ExpandableQueryAttribute: Attribute {
private LambdaExpression someLambda;
//ctor
public ExpandableQueryMethodAttribute(LambdaExpression expression)
{
someLambda = expression
}
}

//usage:
static LambdaExpression exp =
(Expression<Func<IQueryable<Person>, Person>>)
(p => p.FirstOrDefault());

[ExpandableQueryAttribute(exp)] //error here
// "An attribute argument must be a constant expression, typeof expression
// or array creation expression of an attribute parameter type"

我的目标是在属性的构造函数中指定一个方法或 lambda(即使我必须声明一个完整命名的方法并以某种方式传递该方法的名称,这也很好)。

  1. 参数类型可以改变,但重要的是属性构造函数可以采用该参数并以某种方式能够将其分配给 LambdaExpression 类型的字段

  2. 我希望 lambda/方法的声明刚好在对属性构造函数的调用之上,或者内联,这样您就不必走太远就能看到正在传递的内容。

所以这些替代方案会很好,但没有运气让它们工作:

public static ... FuncName(...){...}

[ExpandableQueryAttribute(FuncName)]
// ...

//lambdas aren't allowed inline for an attribute, as far as I know
[ExpandableQueryAttribute(q => q.FirstOrDefault())]
// ...

现有的解决方法是将数字 ID 传递给构造函数(满足“参数必须是常量”的要求),构造函数使用它在先前已添加表达式的字典中进行查找。希望改进/简化这一点,但我觉得由于属性构造函数的限制,它并没有变得更好。

最佳答案

这个怎么样:

    class ExpandableQueryAttribute : Attribute
{

private LambdaExpression someLambda;
//ctor
public ExpandableQueryAttribute(Type hostingType, string filterMethod)
{
someLambda = (LambdaExpression)hostingType.GetField(filterMethod).GetValue(null);
// could also use a static method
}
}

这应该允许您将 lambda 分配给一个字段,然后在运行时将其吸入,尽管通常我更愿意使用 PostSharp 之类的东西在编译时执行此操作。

简单使用示例

    public class LambdaExpressionAttribute : Attribute
{
public LambdaExpression MyLambda { get; private set; }
//ctor
public LambdaExpressionAttribute(Type hostingType, string filterMethod)
{
MyLambda = (LambdaExpression)hostingType.GetField(filterMethod).GetValue(null);
}
}

public class User
{
public bool IsAdministrator { get; set; }
}

public static class securityExpresions
{
public static readonly LambdaExpression IsAdministrator = (Expression<Predicate<User>>)(x => x.IsAdministrator);
public static readonly LambdaExpression IsValid = (Expression<Predicate<User>>)(x => x != null);

public static void CheckAccess(User user)
{
// only for this POC... never do this in shipping code
System.Diagnostics.StackTrace stackTrace = new System.Diagnostics.StackTrace();
var method = stackTrace.GetFrame(1).GetMethod();

var filters = method.GetCustomAttributes(typeof(LambdaExpressionAttribute), true).OfType<LambdaExpressionAttribute>();
foreach (var filter in filters)
{
if ((bool)filter.MyLambda.Compile().DynamicInvoke(user) == false)
{
throw new UnauthorizedAccessException("user does not have access to: " + method.Name);
}
}

}
}

public static class TheClass
{
[LambdaExpression(typeof(securityExpresions), "IsValid")]
public static void ReadSomething(User user, object theThing)
{
securityExpresions.CheckAccess(user);
Console.WriteLine("read something");
}

[LambdaExpression(typeof(securityExpresions), "IsAdministrator")]
public static void WriteSomething(User user, object theThing)
{
securityExpresions.CheckAccess(user);
Console.WriteLine("wrote something");
}

}


static void Main(string[] args)
{

User u = new User();
try
{
TheClass.ReadSomething(u, new object());
TheClass.WriteSomething(u, new object());
}
catch(Exception e)
{
Console.WriteLine(e);
}
}

关于c# - 使用 Lambda 的属性构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11004909/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com