Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 带动态参数的动态lambda表达式_C#_.net_Dynamic_Lambda - Fatal编程技术网

C# 带动态参数的动态lambda表达式

C# 带动态参数的动态lambda表达式,c#,.net,dynamic,lambda,C#,.net,Dynamic,Lambda,鉴于这一类 public class Foo { public string Name { get; set; } } 此方法(在其他类中) private Func Compile(字符串体) { ParameterExpression prm=表达式参数(typeof(Foo),“Foo”); LambdaExpression exp=DynamicExpressionParser.ParseLambda(new[]{prm},typeof(string),body); 返回(Fu

鉴于这一类

public class Foo
{
    public string Name { get; set; }
}
此方法(在其他类中)

private Func Compile(字符串体)
{
ParameterExpression prm=表达式参数(typeof(Foo),“Foo”);
LambdaExpression exp=DynamicExpressionParser.ParseLambda(new[]{prm},typeof(string),body);
返回(Func)exp.Compile();
}
将获取lambda表达式的右侧,并返回一个委托。所以如果这样称呼它:

Foo f = new Foo { Name = "Hamilton Academicals" };
//foo => foo.Name.Substring(0,3)
Func<Foo, string> fn = Compile("foo.Name.Substring(0,3)");
string sub = fn(f);
Foo f=new Foo{Name=“Hamilton Academicals”};
//foo=>foo.Name.Substring(0,3)
Func fn=Compile(“foo.Name.Substring(0,3)”;
字符串sub=fn(f);
然后sub将具有值“Ham”

好吧,不过,我想创建Foo子类DynamicObject(这样我就可以实现TryGetMember来动态地计算属性值),所以我想使用表达式并得到与此等价的结果

Func<dynamic, dynamic> fn = foo => foo.Name.Substring(0,3);
Func-fn=foo=>foo.Name.Substring(0,3);

我曾尝试使用自定义的
CallSiteBinder
来实现
Expression.Dynamic
,但由于类型
Object
中不存在属性或字段
Bar
(当我尝试动态访问
foo.Bar
)而失败。我假设这是因为get
foo.Bar
的调用需要动态调度(使用
Expression.Dynamic
),但这对我不起作用,因为一个关键目标是用户可以输入一个简单的表达式并执行它。有可能吗?

如果这能帮你解决问题,我会让它工作的:

编译器

using System;
using System.Linq.Dynamic.Core;
using System.Linq.Expressions;


namespace ConsoleApp4
{
    public class Compiler
    {
        public static Func<CustomDynamic, TResult> Compile<TResult>(string body)
        {
            ParameterExpression prm = Expression.Parameter(typeof(CustomDynamic), typeof(CustomDynamic).Name);
            LambdaExpression exp = DynamicExpressionParser.ParseLambda(new[] { prm }, typeof(TResult), body);
            return (Func<CustomDynamic, TResult>)exp.Compile();
        }
    }
}
using System.Collections.Generic;
using System.Dynamic;

namespace ConsoleApp4
{
    public class CustomDynamic
    {
        ExpandoObject _values;
        public CustomDynamic()
        {
            _values = new ExpandoObject();
        }

        public void AddProperty(string propertyName, object propertyValue)
        {
            var expandoDict = _values as IDictionary<string, object>;
            if (expandoDict.ContainsKey(propertyName))
                expandoDict[propertyName] = propertyValue;
            else
                expandoDict.Add(propertyName, propertyValue);
        }

        public string GetString(string propertyName)
        {
            var expandoDict = _values as IDictionary<string, object>;
            if (expandoDict.ContainsKey(propertyName))
                return (string)expandoDict[propertyName];
            else
                throw new KeyNotFoundException($"dynamic object did not contain property {propertyName}");
        }
        public int GetInt(string propertyName)
        {
            var expandoDict = _values as IDictionary<string, object>;
            if (expandoDict.ContainsKey(propertyName))
                return (int)expandoDict[propertyName];
            else
                throw new KeyNotFoundException($"dynamic object did not contain property {propertyName}");
        }
    }
}
使用系统;
使用System.Linq.Dynamic.Core;
使用System.Linq.Expressions;
名称空间控制台EAPP4
{
公共类编译器
{
公共静态Func编译(字符串体)
{
ParameterExpression prm=表达式.Parameter(typeof(CustomDynamic)、typeof(CustomDynamic).Name);
LambdaExpression exp=DynamicExpressionParser.ParseLambda(new[]{prm},typeof(TResult),body);
返回(Func)exp.Compile();
}
}
}
动态对象

using System;
using System.Linq.Dynamic.Core;
using System.Linq.Expressions;


namespace ConsoleApp4
{
    public class Compiler
    {
        public static Func<CustomDynamic, TResult> Compile<TResult>(string body)
        {
            ParameterExpression prm = Expression.Parameter(typeof(CustomDynamic), typeof(CustomDynamic).Name);
            LambdaExpression exp = DynamicExpressionParser.ParseLambda(new[] { prm }, typeof(TResult), body);
            return (Func<CustomDynamic, TResult>)exp.Compile();
        }
    }
}
using System.Collections.Generic;
using System.Dynamic;

namespace ConsoleApp4
{
    public class CustomDynamic
    {
        ExpandoObject _values;
        public CustomDynamic()
        {
            _values = new ExpandoObject();
        }

        public void AddProperty(string propertyName, object propertyValue)
        {
            var expandoDict = _values as IDictionary<string, object>;
            if (expandoDict.ContainsKey(propertyName))
                expandoDict[propertyName] = propertyValue;
            else
                expandoDict.Add(propertyName, propertyValue);
        }

        public string GetString(string propertyName)
        {
            var expandoDict = _values as IDictionary<string, object>;
            if (expandoDict.ContainsKey(propertyName))
                return (string)expandoDict[propertyName];
            else
                throw new KeyNotFoundException($"dynamic object did not contain property {propertyName}");
        }
        public int GetInt(string propertyName)
        {
            var expandoDict = _values as IDictionary<string, object>;
            if (expandoDict.ContainsKey(propertyName))
                return (int)expandoDict[propertyName];
            else
                throw new KeyNotFoundException($"dynamic object did not contain property {propertyName}");
        }
    }
}
使用System.Collections.Generic;
运用系统动力学;
名称空间控制台EAPP4
{
公共类自定义动态
{
ExpandoObject_值;
公共自定义动态()
{
_值=新的ExpandoObject();
}
公共void AddProperty(字符串propertyName、对象propertyValue)
{
var expandoDict=_值作为IDictionary;
if(expandoDict.ContainsKey(propertyName))
expandoDict[propertyName]=propertyValue;
其他的
expandoDict.Add(propertyName,propertyValue);
}
公共字符串GetString(字符串属性名称)
{
var expandoDict=_值作为IDictionary;
if(expandoDict.ContainsKey(propertyName))
返回(字符串)expandoDict[propertyName];
其他的
抛出新的KeyNotFoundException($“动态对象未包含属性{propertyName}”);
}
public int GetInt(字符串属性名称)
{
var expandoDict=_值作为IDictionary;
if(expandoDict.ContainsKey(propertyName))
返回(int)expandoDict[propertyName];
其他的
抛出新的KeyNotFoundException($“动态对象未包含属性{propertyName}”);
}
}
}
用例:

using System;

namespace ConsoleApp4
{
    class Program
    {
        static void Main(string[] args)
        {
            CustomDynamic f = new CustomDynamic();
            f.AddProperty("Name", "Hamiltonian Physics");

            Func<CustomDynamic, string> fn = Compiler.Compile<string>("CustomDynamic.GetString(\"Name\").SubString(0, 3)");

            string sub = fn(f);

            Console.WriteLine(sub);
            Console.ReadLine();
        }
    }
}
使用系统;
名称空间控制台EAPP4
{
班级计划
{
静态void Main(字符串[]参数)
{
CustomDynamic f=新的CustomDynamic();
f、 AddProperty(“名称”,“哈密顿物理”);
Func fn=Compiler.Compile(“CustomDynamic.GetString(\“Name\”).SubString(0,3)”;
字符串sub=fn(f);
控制台写入线(sub);
Console.ReadLine();
}
}
}
它只使用
ExpandoObject
类。不幸的是,您需要通过它的API来创建对象,比如为每个属性创建“AddProperty”,但heyho除外


DynamicExpressionParser.ParseLambda
在涉及泛型方法时也有点麻烦,因此我必须创建特定于类型的访问器,虽然它不是最好的,但它正在工作。

为此,我假设您需要另一个专门处理动态表达式的解析器。这个不行。也许只是使用完整的编译器(Roslyn)?需要多复杂的表达式?@Evk-yesp。在我发帖后,我得出了同样的结论。表达式将很简单(一行)。无法使用Roslyn,因为生成的程序集不符合垃圾收集的条件。您可以将生成的程序集加载到单独的应用程序域中并将其拆下。当然,这会影响性能,通常不是很好的解决方案,但可能会比什么都没有好,这取决于您对性能的要求。。。除非我想针对.NETCorewell,否则我认为你就不走运了,至少在他们在.NETCore中实现dll卸载之前是这样(据我所知,这是即将推出的功能)。实现您自己的解析器来处理动态表达式可能并不简单。