从数组中构建匿名类型

问题描述 投票:0回答:1

我正在尝试使用新的Roslyn脚本模块。这是如何使用它的一个例子。请注意,Globals似乎需要是class

public class Globals
{
    public int X;
    public int Y;
}

var globals = new Globals { X = 1, Y = 2 };
Console.WriteLine(await CSharpScript.EvaluateAsync<int>("X+Y", globals: globals));

我有一个generic function采用类型T,数组的长度不确定(但在大多数情况下相对较小的长度):

void Func<T>()
{
   T[] values;
}

如何将T[]转换为anonymous type

所以如果我有T,如果是decimal类型,在这种情况下,values长度为3,

values[0] = 124.3, values[1] = 132.4, values[2] = 23

我想创建一个看起来像这样的anonymous type

var v = new { v1 = 124.3, v2 = 232.4, v3 = 23 };

这可能吗?也就是说,从一个你不知道编译时长度的数组创建一个匿名类型?

注意:这就是为什么我需要一个匿名类型,而不是一个元组,或一个List等等。而且,因为我不知道数组有多大,我不能硬连线一个类

编辑1

当我尝试下面给出的解决方案时,我甚至感到震惊,这甚至编译:

dynamic v = new ExpandoObject();
var dictionary = (IDictionary<string, object>)v;            

dictionary.Add("X", 1.5);
dictionary.Add("Y", 2.7);

//var globals = new Globals { X = 1.5, Y = 2.7 };
var retval = CSharpScript.EvaluateAsync<double>("System.Math.Sqrt(System.Math.Log(X + Y))", 
                      globals: dictionary).GetAwaiter();

//retval = (decimal)Convert.ChangeType(retval, typeof(decimal));

Console.WriteLine(retval.GetResult());

遗憾的是,我收到运行时错误:

Microsoft.CodeAnalysis.Scripting.CompilationErrorException
  HResult=0x80131500
  Message=(1,34): error CS0103: The name 'X' does not exist in the current context
  Source=Microsoft.CodeAnalysis.Scripting
  StackTrace:
   at Microsoft.CodeAnalysis.Scripting.ScriptBuilder.ThrowIfAnyCompilationErrors(DiagnosticBag diagnostics, DiagnosticFormatter formatter)
   at Microsoft.CodeAnalysis.Scripting.ScriptBuilder.CreateExecutor[T](ScriptCompiler compiler, Compilation compilation, Boolean emitDebugInformation, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.Scripting.Script`1.GetExecutor(CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.Scripting.Script`1.RunAsync(Object globals, Func`2 catchException, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.CSharp.Scripting.CSharpScript.RunAsync[T](String code, ScriptOptions options, Object globals, Type globalsType, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.CSharp.Scripting.CSharpScript.EvaluateAsync[T](String code, ScriptOptions options, Object globals, Type globalsType, CancellationToken cancellationToken)
   at Trady.Form1.InitializeScriptEngineAsync() in C:\Users\idf\Form1.cs:line 79
   at Form1..ctor() in C:\Users\idf\Form1.cs:line 56
   at Trady.Program.Main() in C:\Users\idf\Program.cs:line 19
c# anonymous-types c#-7.0
1个回答
1
投票

问题是匿名类型是自动生成的类型,它们在编译时被修复。所以它是一个静态类型的动态类型。

ExpandoObject是与dynamic关键字一起使用的对象,用于动态添加属性和方法。

以下是您的功能示例:

void Func<T>()
{
    T[] values;
    dynamic v = new ExpandoObject();
    var dictionary = (IDictionary<string, object>)v;
    var i = 0;
    foreach (var value in values)
    {
        i++;
        dictionary.Add($"v{i}", value);
    }
}

ExpandoObject实现了IDictionary接口,因此可以强制转换为它,以便动态添加属性。

© www.soinside.com 2019 - 2024. All rights reserved.