Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/326.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# 将动态类型的属性添加到动态类型_C# - Fatal编程技术网

C# 将动态类型的属性添加到动态类型

C# 将动态类型的属性添加到动态类型,c#,C#,我正在尝试创建类似以下内容的动态类型: public class DataObjects { public DataObjectsLesser1 SomeRandom0 { get; } public DataObjectsLesser2 SomeRandom1 { get; } } public class DataObjectsLesser1 { public int Prop0 { get; } } public class DataObjectsLesser2 {

我正在尝试创建类似以下内容的动态类型:

public class DataObjects
{
  public DataObjectsLesser1 SomeRandom0 { get; }
  public DataObjectsLesser2 SomeRandom1 { get; }
}

public class DataObjectsLesser1 
{
  public int Prop0 { get; }
}

public class DataObjectsLesser2
{
  public int Prop0 { get; }
}
下面的完整代码示例是real程序的简化版本,它使用第三方api创建树结构,您可以在其中导航嵌套类型


在实际的程序中,我可以轻松地创建顶级类型的DataObjects,以及DataObjectsLesser1/2的空版本。问题是,当我想创建DataObjectsLesser1/2的属性时——如果要复制错误——则忽略最内部循环中的值“Prop”+num,而将值“SomeRandom”+I*10用作属性名称。我看不出有任何逻辑上的原因,因为类型是按预期设置的(示例中为int)

我也不知道如何验证示例中发生了什么。我在实例变量中获得了一个动态类型,其中包含我生成的属性,但每个属性都不显示为类型化的-只有null属性,无法说明生成了什么类型。我需要浏览对象图进行测试

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Threading;

namespace TyeTes
{
    internal class Program
    {
        private static void CreateProperty(TypeBuilder typeBuilder, Type propertyType, string propertyName)
        {
            FieldBuilder fieldBuilder = typeBuilder.DefineField(propertyName + "X", propertyType, FieldAttributes.Private);
            PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, null);
            MethodBuilder propertyGetter = typeBuilder.DefineMethod("get_" + propertyName, MethodAttributes.Public |
                                                MethodAttributes.SpecialName | MethodAttributes.HideBySig, propertyType, Type.EmptyTypes);
            ILGenerator randomPropertyGetterIL = propertyGetter.GetILGenerator();
            randomPropertyGetterIL.Emit(OpCodes.Ldarg_0);
            randomPropertyGetterIL.Emit(OpCodes.Ldfld, fieldBuilder);
            randomPropertyGetterIL.Emit(OpCodes.Ret);
            propertyBuilder.SetGetMethod(propertyGetter);
        }

        private static void Main(string[] args)
        {
            var assembly = new AssemblyName("FieldTypes");
            AssemblyBuilder assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(assembly, AssemblyBuilderAccess.Run);
            ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(assembly.Name);
            TypeBuilder typeBuilder = DefineType(moduleBuilder, "DataObjects");

            foreach (var i in Enumerable.Range(0, 3))
            {
                TypeBuilder subTypeBuilder = DefineType(moduleBuilder, "DataObjectsLesser" + i);
                foreach (var num in Enumerable.Range(0, 2))
                {
                    CreateProperty(subTypeBuilder, typeof(int), "Prop" + num);
                }
                CreateProperty(typeBuilder, subTypeBuilder.CreateType(), "SomeRandom" + i * 10);
            }
            Type randomType = typeBuilder.CreateType();
            var instance = Activator.CreateInstance(randomType);
        }

        public static TypeBuilder DefineType(ModuleBuilder modBuilder, string typeName)
        {
            TypeBuilder typeBuilder = modBuilder.DefineType(typeName,
                TypeAttributes.Public |
                TypeAttributes.Class |
                TypeAttributes.AutoClass |
                TypeAttributes.AnsiClass |
                TypeAttributes.BeforeFieldInit |
                TypeAttributes.AutoLayout,
                typeof(object));
            return typeBuilder;
        }
    }
}

关于你的第二个问题:

我需要浏览对象图进行测试

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Threading;

namespace TyeTes
{
    internal class Program
    {
        private static void CreateProperty(TypeBuilder typeBuilder, Type propertyType, string propertyName)
        {
            FieldBuilder fieldBuilder = typeBuilder.DefineField(propertyName + "X", propertyType, FieldAttributes.Private);
            PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, null);
            MethodBuilder propertyGetter = typeBuilder.DefineMethod("get_" + propertyName, MethodAttributes.Public |
                                                MethodAttributes.SpecialName | MethodAttributes.HideBySig, propertyType, Type.EmptyTypes);
            ILGenerator randomPropertyGetterIL = propertyGetter.GetILGenerator();
            randomPropertyGetterIL.Emit(OpCodes.Ldarg_0);
            randomPropertyGetterIL.Emit(OpCodes.Ldfld, fieldBuilder);
            randomPropertyGetterIL.Emit(OpCodes.Ret);
            propertyBuilder.SetGetMethod(propertyGetter);
        }

        private static void Main(string[] args)
        {
            var assembly = new AssemblyName("FieldTypes");
            AssemblyBuilder assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(assembly, AssemblyBuilderAccess.Run);
            ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(assembly.Name);
            TypeBuilder typeBuilder = DefineType(moduleBuilder, "DataObjects");

            foreach (var i in Enumerable.Range(0, 3))
            {
                TypeBuilder subTypeBuilder = DefineType(moduleBuilder, "DataObjectsLesser" + i);
                foreach (var num in Enumerable.Range(0, 2))
                {
                    CreateProperty(subTypeBuilder, typeof(int), "Prop" + num);
                }
                CreateProperty(typeBuilder, subTypeBuilder.CreateType(), "SomeRandom" + i * 10);
            }
            Type randomType = typeBuilder.CreateType();
            var instance = Activator.CreateInstance(randomType);
        }

        public static TypeBuilder DefineType(ModuleBuilder modBuilder, string typeName)
        {
            TypeBuilder typeBuilder = modBuilder.DefineType(typeName,
                TypeAttributes.Public |
                TypeAttributes.Class |
                TypeAttributes.AutoClass |
                TypeAttributes.AnsiClass |
                TypeAttributes.BeforeFieldInit |
                TypeAttributes.AutoLayout,
                typeof(object));
            return typeBuilder;
        }
    }
}
我想到的最简单的方法是将动态程序集保存到磁盘,然后在或其他反编译器中查看它。为此,请指定
AssemblyBuilderAccess.RunAndSave
选项到
defineddynamicassembly
方法,并在
defineddynamicmodule
方法中提供文件名:

AssemblyBuilder assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(assembly, AssemblyBuilderAccess.RunAndSave);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule(assembly.Name, 
                                                                 "temp.dll");
然后在末尾添加:

assemblyBuilder.Save("temp.dll");

“如果要复制错误”?我已经试过你的代码,它似乎工作正常,所以我想知道我们能如何帮助你。@konRadkokosa我的最后一段呢?谢谢,正如我在回答中所说的,我建议简单地将其保存到磁盘。我恐怕这不起作用,错误消息出现在第一行:mscorlib.dll中出现“System.NotSupportedException”类型的未处理异常。其他信息:瞬态程序集中不能有持久化模块。这也是需要定义的DynamicAssembly(assembly,AssemblyBuilderAccess.RunAndSave),请更新您的answer@Jaycee是的,我忘记提了。我刚刚更新了我的答案。