简体   繁体   English

C# 匿名 object 具有字典中的属性

[英]C# anonymous object with properties from dictionary

I'm trying to convert an dictionary to an anonymous type with one property for every Key.我正在尝试将字典转换为匿名类型,每个键都有一个属性。

I tried google it but all I could find was how to convert a anonymous object to a dictionary.我尝试用谷歌搜索,但我所能找到的只是如何将匿名 object 转换为字典。

My dictionary looks something like this:我的字典看起来像这样:

var dict = new Dictionary<string, string>
{
    {"Id", "1"},
    {"Title", "My title"},
    {"Description", "Blah blah blah"},
};

And i would like to return a anonymous object that looks like this.我想返回一个匿名的 object,看起来像这样。

var o = new 
{
    Id = "1",
    Title = "My title",
    Description = "Blah blah blah"
};

So I would like it to loop thru every keyValuePair in the dictionary and create a property in the object for every key.所以我希望它遍历字典中的每个 keyValuePair 并在 object 中为每个键创建一个属性。

I don't know where to begin.我不知道从哪里开始。

Please help.请帮忙。

You can't, basically. 基本上你不能。 Anonymous types are created by the compiler, so they exist in your assembly with all the property names baked into them. 匿名类型由编译器创建,因此它们存在于程序集中,其中包含所有属性名称。 (The property types aren't a problem in this case - as an implementation detail, the compiler creates a generic type and then creates an instance of that using appropriate type arguments.) (在这种情况下,属性类型不是问题 - 作为实现细节,编译器创建泛型类型,然后使用适当的类型参数创建该实例。)

You're asking for a type with properties which are determined at execution time - which just doesn't fit with how anonymous types work. 您要求的类型具有在执行时确定的属性 - 这与匿名类型的工作方式不符。 You'd have to basically compile code using it at execution time - which would then be a pain as it would be in a different assembly, and anonymous types are internal... 你必须在执行时基本上使用它来编译代码 - 这将是一个痛苦,因为它将在不同的程序集中,并且匿名类型是内部的......

Perhaps you should use ExpandoObject instead? 也许您应该使用ExpandoObject代替? Then anything using dynamic will be able to access the properties as normal. 然后使用dynamic任何东西都能正常访问属性。

Now, at least once a month someone asks how to create an anonymous type at runtime... Here is the response: 现在,至少每月一次有人询问如何在运行时创建匿名类型......以下是响应:

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;

/// <summary>
/// The code generated should be nearly equal to the one generated by
/// csc 12.0.31101.0 when compiling with /optimize+ /debug-. The main
/// difference is in the GetHashCode() (the base init_hash used is 
/// compiler-dependant) and in the maxstack of the generated methods.
/// Note that Roslyn (at least the one present at 
/// tryroslyn.azurewebsites.net) generates different code for anonymous
/// types.
/// </summary>
public static class AnonymousType
{
    private static readonly ConcurrentDictionary<string, Type> GeneratedTypes = new ConcurrentDictionary<string, Type>();

    private static readonly AssemblyBuilder AssemblyBuilder;
    private static readonly ModuleBuilder ModuleBuilder;
    private static readonly string FileName;

    // Some objects we cache
    private static readonly CustomAttributeBuilder CompilerGeneratedAttributeBuilder = new CustomAttributeBuilder(typeof(CompilerGeneratedAttribute).GetConstructor(Type.EmptyTypes), new object[0]);
    private static readonly CustomAttributeBuilder DebuggerBrowsableAttributeBuilder = new CustomAttributeBuilder(typeof(DebuggerBrowsableAttribute).GetConstructor(new[] { typeof(DebuggerBrowsableState) }), new object[] { DebuggerBrowsableState.Never });
    private static readonly CustomAttributeBuilder DebuggerHiddenAttributeBuilder = new CustomAttributeBuilder(typeof(DebuggerHiddenAttribute).GetConstructor(Type.EmptyTypes), new object[0]);

    private static readonly ConstructorInfo ObjectCtor = typeof(object).GetConstructor(Type.EmptyTypes);
    private static readonly MethodInfo ObjectToString = typeof(object).GetMethod("ToString", BindingFlags.Instance | BindingFlags.Public, null, Type.EmptyTypes, null);

    private static readonly ConstructorInfo StringBuilderCtor = typeof(StringBuilder).GetConstructor(Type.EmptyTypes);
    private static readonly MethodInfo StringBuilderAppendString = typeof(StringBuilder).GetMethod("Append", BindingFlags.Instance | BindingFlags.Public, null, new[] { typeof(string) }, null);
    private static readonly MethodInfo StringBuilderAppendObject = typeof(StringBuilder).GetMethod("Append", BindingFlags.Instance | BindingFlags.Public, null, new[] { typeof(object) }, null);

    private static readonly Type EqualityComparer = typeof(EqualityComparer<>);
    private static readonly Type EqualityComparerGenericArgument = EqualityComparer.GetGenericArguments()[0];
    private static readonly MethodInfo EqualityComparerDefault = EqualityComparer.GetMethod("get_Default", BindingFlags.Static | BindingFlags.Public, null, Type.EmptyTypes, null);
    private static readonly MethodInfo EqualityComparerEquals = EqualityComparer.GetMethod("Equals", BindingFlags.Instance | BindingFlags.Public, null, new[] { EqualityComparerGenericArgument, EqualityComparerGenericArgument }, null);
    private static readonly MethodInfo EqualityComparerGetHashCode = EqualityComparer.GetMethod("GetHashCode", BindingFlags.Instance | BindingFlags.Public, null, new[] { EqualityComparerGenericArgument }, null);

    private static int Index = -1;

    static AnonymousType()
    {
        var assemblyName = new AssemblyName("AnonymousTypes");

        FileName = assemblyName.Name + ".dll";

        AssemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
        ModuleBuilder = AssemblyBuilder.DefineDynamicModule("AnonymousTypes", FileName);
    }

    public static void Dump()
    {
        AssemblyBuilder.Save(FileName);
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="types"></param>
    /// <param name="names"></param>
    /// <returns></returns>
    public static Type CreateType(Type[] types, string[] names)
    {
        if (types == null)
        {
            throw new ArgumentNullException("types");
        }

        if (names == null)
        {
            throw new ArgumentNullException("names");
        }

        if (types.Length != names.Length)
        {
            throw new ArgumentException("names");
        }

        // Anonymous classes are generics based. The generic classes
        // are distinguished by number of parameters and name of 
        // parameters. The specific types of the parameters are the 
        // generic arguments. We recreate this by creating a fullName
        // composed of all the property names, separated by a "|"
        string fullName = string.Join("|", names.Select(x => Escape(x)));

        Type type;

        if (!GeneratedTypes.TryGetValue(fullName, out type))
        {
            // We create only a single class at a time, through this lock
            // Note that this is a variant of the double-checked locking.
            // It is safe because we are using a thread safe class.
            lock (GeneratedTypes)
            {
                if (!GeneratedTypes.TryGetValue(fullName, out type))
                {
                    int index = Interlocked.Increment(ref Index);

                    string name = names.Length != 0 ? string.Format("<>f__AnonymousType{0}`{1}", index, names.Length) : string.Format("<>f__AnonymousType{0}", index);
                    TypeBuilder tb = ModuleBuilder.DefineType(name, TypeAttributes.AnsiClass | TypeAttributes.Class | TypeAttributes.AutoLayout | TypeAttributes.NotPublic | TypeAttributes.Sealed | TypeAttributes.BeforeFieldInit);
                    tb.SetCustomAttribute(CompilerGeneratedAttributeBuilder);

                    GenericTypeParameterBuilder[] generics = null;

                    if (names.Length != 0)
                    {
                        string[] genericNames = Array.ConvertAll(names, x => string.Format("<{0}>j__TPar", x));
                        generics = tb.DefineGenericParameters(genericNames);
                    }
                    else
                    {
                        generics = new GenericTypeParameterBuilder[0];
                    }

                    // .ctor
                    ConstructorBuilder constructor = tb.DefineConstructor(MethodAttributes.Public | MethodAttributes.HideBySig, CallingConventions.HasThis, generics);
                    constructor.SetCustomAttribute(DebuggerHiddenAttributeBuilder);
                    ILGenerator ilgeneratorConstructor = constructor.GetILGenerator();
                    ilgeneratorConstructor.Emit(OpCodes.Ldarg_0);
                    ilgeneratorConstructor.Emit(OpCodes.Call, ObjectCtor);

                    var fields = new FieldBuilder[names.Length];

                    // There are two for cycles because we want to have
                    // all the getter methods before all the other 
                    // methods
                    for (int i = 0; i < names.Length; i++)
                    {
                        // field
                        fields[i] = tb.DefineField(string.Format("<{0}>i__Field", names[i]), generics[i], FieldAttributes.Private | FieldAttributes.InitOnly);
                        fields[i].SetCustomAttribute(DebuggerBrowsableAttributeBuilder);

                        // .ctor
                        constructor.DefineParameter(i + 1, ParameterAttributes.None, names[i]);
                        ilgeneratorConstructor.Emit(OpCodes.Ldarg_0);

                        if (i == 0)
                        {
                            ilgeneratorConstructor.Emit(OpCodes.Ldarg_1);
                        }
                        else if (i == 1)
                        {
                            ilgeneratorConstructor.Emit(OpCodes.Ldarg_2);
                        }
                        else if (i == 2)
                        {
                            ilgeneratorConstructor.Emit(OpCodes.Ldarg_3);
                        }
                        else if (i < 255)
                        {
                            ilgeneratorConstructor.Emit(OpCodes.Ldarg_S, (byte)(i + 1));
                        }
                        else
                        {
                            // Ldarg uses a ushort, but the Emit only
                            // accepts short, so we use a unchecked(...),
                            // cast to short and let the CLR interpret it
                            // as ushort
                            ilgeneratorConstructor.Emit(OpCodes.Ldarg, unchecked((short)(i + 1)));
                        }

                        ilgeneratorConstructor.Emit(OpCodes.Stfld, fields[i]);

                        // getter
                        MethodBuilder getter = tb.DefineMethod(string.Format("get_{0}", names[i]), MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName, CallingConventions.HasThis, generics[i], Type.EmptyTypes);
                        ILGenerator ilgeneratorGetter = getter.GetILGenerator();
                        ilgeneratorGetter.Emit(OpCodes.Ldarg_0);
                        ilgeneratorGetter.Emit(OpCodes.Ldfld, fields[i]);
                        ilgeneratorGetter.Emit(OpCodes.Ret);

                        PropertyBuilder property = tb.DefineProperty(names[i], PropertyAttributes.None, CallingConventions.HasThis, generics[i], Type.EmptyTypes);
                        property.SetGetMethod(getter);
                    }

                    // ToString()
                    MethodBuilder toString = tb.DefineMethod("ToString", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, CallingConventions.HasThis, typeof(string), Type.EmptyTypes);
                    toString.SetCustomAttribute(DebuggerHiddenAttributeBuilder);
                    ILGenerator ilgeneratorToString = toString.GetILGenerator();

                    ilgeneratorToString.DeclareLocal(typeof(StringBuilder));

                    ilgeneratorToString.Emit(OpCodes.Newobj, StringBuilderCtor);
                    ilgeneratorToString.Emit(OpCodes.Stloc_0);

                    // Equals
                    MethodBuilder equals = tb.DefineMethod("Equals", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, CallingConventions.HasThis, typeof(bool), new[] { typeof(object) });
                    equals.SetCustomAttribute(DebuggerHiddenAttributeBuilder);
                    equals.DefineParameter(1, ParameterAttributes.None, "value");
                    ILGenerator ilgeneratorEquals = equals.GetILGenerator();
                    ilgeneratorEquals.DeclareLocal(tb);

                    ilgeneratorEquals.Emit(OpCodes.Ldarg_1);
                    ilgeneratorEquals.Emit(OpCodes.Isinst, tb);
                    ilgeneratorEquals.Emit(OpCodes.Stloc_0);
                    ilgeneratorEquals.Emit(OpCodes.Ldloc_0);

                    Label equalsLabel = ilgeneratorEquals.DefineLabel();

                    // GetHashCode()
                    MethodBuilder getHashCode = tb.DefineMethod("GetHashCode", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig, CallingConventions.HasThis, typeof(int), Type.EmptyTypes);
                    getHashCode.SetCustomAttribute(DebuggerHiddenAttributeBuilder);
                    ILGenerator ilgeneratorGetHashCode = getHashCode.GetILGenerator();
                    ilgeneratorGetHashCode.DeclareLocal(typeof(int));

                    if (names.Length == 0)
                    {
                        ilgeneratorGetHashCode.Emit(OpCodes.Ldc_I4_0);
                    }
                    else
                    {
                        // As done by Roslyn
                        // Note that initHash can vary, because
                        // string.GetHashCode() isn't "stable" for 
                        // different compilation of the code
                        int initHash = 0;

                        for (int i = 0; i < names.Length; i++)
                        {
                            initHash = unchecked(initHash * (-1521134295) + fields[i].Name.GetHashCode());
                        }

                        // Note that the CSC seems to generate a 
                        // different seed for every anonymous class
                        ilgeneratorGetHashCode.Emit(OpCodes.Ldc_I4, initHash);
                    }

                    for (int i = 0; i < names.Length; i++)
                    {
                        // Equals()
                        Type equalityComparerT = EqualityComparer.MakeGenericType(generics[i]);
                        MethodInfo equalityComparerTDefault = TypeBuilder.GetMethod(equalityComparerT, EqualityComparerDefault);
                        MethodInfo equalityComparerTEquals = TypeBuilder.GetMethod(equalityComparerT, EqualityComparerEquals);

                        ilgeneratorEquals.Emit(OpCodes.Brfalse_S, equalsLabel);
                        ilgeneratorEquals.Emit(OpCodes.Call, equalityComparerTDefault);
                        ilgeneratorEquals.Emit(OpCodes.Ldarg_0);
                        ilgeneratorEquals.Emit(OpCodes.Ldfld, fields[i]);
                        ilgeneratorEquals.Emit(OpCodes.Ldloc_0);
                        ilgeneratorEquals.Emit(OpCodes.Ldfld, fields[i]);
                        ilgeneratorEquals.Emit(OpCodes.Callvirt, equalityComparerTEquals);

                        // GetHashCode();
                        MethodInfo EqualityComparerTGetHashCode = TypeBuilder.GetMethod(equalityComparerT, EqualityComparerGetHashCode);

                        ilgeneratorGetHashCode.Emit(OpCodes.Stloc_0);
                        ilgeneratorGetHashCode.Emit(OpCodes.Ldc_I4, -1521134295);
                        ilgeneratorGetHashCode.Emit(OpCodes.Ldloc_0);
                        ilgeneratorGetHashCode.Emit(OpCodes.Mul);
                        ilgeneratorGetHashCode.Emit(OpCodes.Call, equalityComparerTDefault);
                        ilgeneratorGetHashCode.Emit(OpCodes.Ldarg_0);
                        ilgeneratorGetHashCode.Emit(OpCodes.Ldfld, fields[i]);
                        ilgeneratorGetHashCode.Emit(OpCodes.Callvirt, EqualityComparerTGetHashCode);
                        ilgeneratorGetHashCode.Emit(OpCodes.Add);

                        // ToString()
                        ilgeneratorToString.Emit(OpCodes.Ldloc_0);
                        ilgeneratorToString.Emit(OpCodes.Ldstr, i == 0 ? string.Format("{{ {0} = ", names[i]) : string.Format(", {0} = ", names[i]));
                        ilgeneratorToString.Emit(OpCodes.Callvirt, StringBuilderAppendString);
                        ilgeneratorToString.Emit(OpCodes.Pop);
                        ilgeneratorToString.Emit(OpCodes.Ldloc_0);
                        ilgeneratorToString.Emit(OpCodes.Ldarg_0);
                        ilgeneratorToString.Emit(OpCodes.Ldfld, fields[i]);
                        ilgeneratorToString.Emit(OpCodes.Box, generics[i]);
                        ilgeneratorToString.Emit(OpCodes.Callvirt, StringBuilderAppendObject);
                        ilgeneratorToString.Emit(OpCodes.Pop);
                    }

                    // .ctor
                    ilgeneratorConstructor.Emit(OpCodes.Ret);

                    // Equals()
                    if (names.Length == 0)
                    {
                        ilgeneratorEquals.Emit(OpCodes.Ldnull);
                        ilgeneratorEquals.Emit(OpCodes.Ceq);
                        ilgeneratorEquals.Emit(OpCodes.Ldc_I4_0);
                        ilgeneratorEquals.Emit(OpCodes.Ceq);
                    }
                    else
                    {
                        ilgeneratorEquals.Emit(OpCodes.Ret);
                        ilgeneratorEquals.MarkLabel(equalsLabel);
                        ilgeneratorEquals.Emit(OpCodes.Ldc_I4_0);
                    }

                    ilgeneratorEquals.Emit(OpCodes.Ret);

                    // GetHashCode()
                    ilgeneratorGetHashCode.Emit(OpCodes.Stloc_0);
                    ilgeneratorGetHashCode.Emit(OpCodes.Ldloc_0);
                    ilgeneratorGetHashCode.Emit(OpCodes.Ret);

                    // ToString()
                    ilgeneratorToString.Emit(OpCodes.Ldloc_0);
                    ilgeneratorToString.Emit(OpCodes.Ldstr, names.Length == 0 ? "{ }" : " }");
                    ilgeneratorToString.Emit(OpCodes.Callvirt, StringBuilderAppendString);
                    ilgeneratorToString.Emit(OpCodes.Pop);
                    ilgeneratorToString.Emit(OpCodes.Ldloc_0);
                    ilgeneratorToString.Emit(OpCodes.Callvirt, ObjectToString);
                    ilgeneratorToString.Emit(OpCodes.Ret);

                    type = tb.CreateType();

                    type = GeneratedTypes.GetOrAdd(fullName, type);
                }
            }
        }

        if (types.Length != 0)
        {
            type = type.MakeGenericType(types);
        }

        return type;
    }

    private static string Escape(string str)
    {
        // We escape the \ with \\, so that we can safely escape the
        // "|" (that we use as a separator) with "\|"
        str = str.Replace(@"\", @"\\");
        str = str.Replace(@"|", @"\|");
        return str;
    }
}

This big, fat, block of code will use Reflection.Emit to generate at runtime some classes with the properties named however you want (you can even use characters that are illegal in C#). 这个庞大的代码块将使用Reflection.Emit在运行时生成一些具有您想要的属性的类(您甚至可以使用在C#中非法的字符)。 These classes will follow the naming conventions of the anonymous classes generated by the C# compiler 12.0.31101.0 . 这些类将遵循C#编译器12.0.31101.0生成的匿名类的命名约定。 They should be nearly equal even at the IL level. 即使在IL水平,它们也应该几乎相等。 All the various Equals() , GetHashCode() and ToString() are implemented as implemented by the C# compiler 12.0.31101.0, all the fields have the same name, the CompilerGeneratedAttribute is inserted (this is morally wrong, I know :-) ) and so on. 所有各种Equals()GetHashCode()ToString()实现为由C#编译器12.0.31101.0实现,所有字段都具有相同的名称,插入CompilerGeneratedAttribute (这在道德上是错误的,我知道:-))等等。 So the classes generated walk like an anonymous duck and quack like an anonymous duck... They are pratically anonymous ducks :-) (note that Roslyn ducks are of a different sub specie... Their plumage is a little different... an anonymous duck connaisseur could easily distinguish the two sub species :-) ) 因此,所产生的课程就像一只匿名的鸭子和庸医就像一只匿名的鸭子......他们是非常匿名的鸭子:-)(请注意,罗斯林的鸭子是不同的亚种......他们的羽毛有点不同......匿名鸭骗子很容易区分这两个亚种:-))

Now, if you want to ask cui prodest? 现在,如果你想问cui prodest? The generated classes can only be used through reflection, so they are difficult to use, but they have a specific use-case, that Marc Gravell individuated: there are parts of the .NET framework that heavily use reflection to render objects (for example all the various datagrids). 生成的类只能通过反射来使用,所以它们很难使用,但它们有一个特定的用例,Marc Gravell个性化:.NET框架的某些部分大量使用反射来渲染对象(例如所有各种数据网格)。 These parts are incompatible with dynamic objects and often don't support object[] . 这些部分与dynamic对象不兼容,通常不支持object[] A solution is often to encapsulate the data in a DataTable ... or you can use this :-) 解决方案通常是将数据封装在DataTable ......或者您可以使用此:-)

In your specific case, you can use this method: 在您的特定情况下,您可以使用此方法:

public static object FromDictToAnonymousObj<TValue>(IDictionary<string, TValue> dict)
{
    var types = new Type[dict.Count];

    for (int i = 0; i < types.Length; i++)
    {
        types[i] = typeof(TValue);
    }

    // dictionaries don't have an order, so we force an order based
    // on the Key
    var ordered = dict.OrderBy(x => x.Key).ToArray();

    string[] names = Array.ConvertAll(ordered, x => x.Key);

    Type type = AnonymousType.CreateType(types, names);

    object[] values = Array.ConvertAll(ordered, x => (object)x.Value);

    object obj = type.GetConstructor(types).Invoke(values);

    return obj;
}

like this: 像这样:

var dict = new Dictionary<string, string>
{
    {"Id", "1"},
    {"Title", "My title"},
    {"Description", "Blah blah blah"},
};

object obj1 = FromDictToAnonymousObj(dict);

to obtain your object. 获得你的对象。

Basically, that isn't something that you can do trivially; 基本上,这不是你可以做的事情; anonymous types still have all the usual code behind the scenes: just you don't see it. 匿名类型仍然拥有幕后的所有常用代码:只是你没有看到它。 What you can do is the same thing via dynamic , but that won't work for APIs that expect reflection etc - so given that you'd have to be accessing by key, for most code dictionary access will be more convenient than an anonymous type or dynamic type. 可以通过dynamic做同样的事情,但这对于期望反射等的API不起作用 - 因此,您必须通过密钥访问,因为大多数代码字典访问将比匿名类型更方便或dynamic类型。

Here's how you could do it as an ExpandoObject (help from this post ) 以下是如何将其作为ExpandoObject本帖的帮助)

var dict = new Dictionary<string, string>
{
    {"Id", "1"},
    {"Title", "My title"},
    {"Description", "Blah blah blah"},
};

var expando = new ExpandoObject()  as IDictionary<string, Object>;
foreach(var kvp in dict)
    expando.Add(kvp.Key, kvp.Value);

It isn't an anonymous object but you can accomplish this with a DynamicObject ! 它不是匿名对象,但您可以使用DynamicObject完成此操作! You could do the following. 您可以执行以下操作。

public class MyExpando : DynamicObject
{
    Dictionary<string, object> dictionary;
    public MyExpando()
    {
       dictionary = new Dictionary<string, object>
       {
            {"Id", "1"},
            {"Title", "My title"},
            {"Description", "Blah blah blah"},
       };
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        return dictionary.TryGetValue(binder.Name, out result);
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        if (!dictionary.ContainsKey(binder.Name))
            return false;
        dictionary[binder.Name] = value;
        return true;
    }
}

Then you have your object with the properties you want. 然后,您的对象具有所需的属性。

dynamic o = new MyExpando();
Console.WriteLine("Id :  " + o.Id + ", Title : " + o.Title + ", Description : " + o.Description);

Downside of course is there is no type checking at compile time and no check to see if the member exists either at compile time. 当然,缺点是在编译时没有类型检查,也没有检查成员是否在编译时存在。

I need it to be able to use enum values in javascript side By using Eval, I have reached a level that will at least work.我需要它能够在 javascript 端使用枚举值通过使用 Eval,我已经达到了至少可以工作的水平。 Maybe it will help you... The url link where I adapted the Eval related codes也许它会对你有所帮助......我改编了Eval相关代码的url链接

public enum ServerTypes { none = 0, uni = 1, home = 2, app = 3 }
public static object ToClass(Type value)
    {
        if (value.IsEnum)
        {
            var info = String.Concat("new {", String.Join(", ", Enum.GetNames(value).Select((x, i) => String.Join(" = ", x, Enum.GetValues(value).GetValue(i).ToInt32().ToString()))), "}");
            var nmspc = typeof(Tools).Namespace;
            var cp = new CompilerParameters();
            cp.ReferencedAssemblies.Add("system.dll");
            cp.CompilerOptions = "/t:library";
            cp.GenerateInMemory = true;
            var sb = new StringBuilder();
            sb.AppendLine(String.Concat("namespace ", nmspc, " { using System; public class CSCodeEvaler { public object EvalCode() { "));
            sb.AppendLine(String.Format("return {0};", info));
            sb.AppendLine(" } } }");
            var cr = new CSharpCodeProvider().CompileAssemblyFromSource(cp, sb.ToString());
            if (cr.Errors.Count > 0) { throw new InvalidExpressionException(String.Format("Error ({0}) evaluating: {1}", cr.Errors[0].ErrorText, info)); }
            else
            {
                var o = cr.CompiledAssembly.CreateInstance(String.Concat(nmspc, ".CSCodeEvaler"));
                return o.GetType().GetMethod("EvalCode").Invoke(o, null);
            }
        }
        else { throw new NotImplementedException("value tipi enum olmalıdır!"); }
    }

And finally result最后结果

在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM