Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cassandra/3.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#_.net_Vb.net_Reflection - Fatal编程技术网

C# 有没有办法在运行时构建新类型?

C# 有没有办法在运行时构建新类型?,c#,.net,vb.net,reflection,C#,.net,Vb.net,Reflection,我要问一个听起来很奇怪的问题 有没有办法在运行时构建一个新类?或者至少向现有类添加一个新属性 我的意思是创建一个不存在的类,而不是现有类的实例。稍后我可以使用反射来加载和使用这个类。看看名称空间。我自己从未使用过它,但是这个名称空间中的类可以用来生成IL(中间语言)。您可以看看名称空间。根据其中一个链接页面: NET Framework包括一种称为代码文档对象模型(CodeDOM)的机制,它使发出源代码的程序的开发人员能够在运行时基于表示要呈现的代码的单个模型以多种编程语言生成源代码 我一点也不

我要问一个听起来很奇怪的问题

有没有办法在运行时构建一个新类?或者至少向现有类添加一个新属性


我的意思是创建一个不存在的类,而不是现有类的实例。稍后我可以使用反射来加载和使用这个类。

看看名称空间。我自己从未使用过它,但是这个名称空间中的类可以用来生成IL(中间语言)。

您可以看看名称空间。根据其中一个链接页面:

NET Framework包括一种称为代码文档对象模型(CodeDOM)的机制,它使发出源代码的程序的开发人员能够在运行时基于表示要呈现的代码的单个模型以多种编程语言生成源代码

我一点也不是这方面的专家,我只是记得在墙上的.NET Framework海报上看到了它。:)


编辑:自从写了这个答案后,我已经玩了一点System.CodeDom。我已经编写了一个应用程序,它使用了一些基本的CodeDom,可以帮助那些想要开始使用它的人。

向现有类型添加属性是不可能的,但是您可以在运行时使用Reflection.Emit创建一个新类型。这是相当复杂的事情,事情是这样的:

AssemblyBuilder assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(
      assemblyName , AssemblyBuilderAccess.Run, assemblyAttributes);
ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("ModuleName");
TypeBuilder typeBuilder = moduleBuilder.DefineType(
      "MyNamespace.TypeName" , TypeAttributes.Public);

typeBuilder.DefineDefaultConstructor(MethodAttributes.Public);

// Add a method
newMethod = typeBuilder.DefineMethod("MethodName" , MethodAttributes.Public);

ILGenerator ilGen = newMethod.GetILGenerator();

// Create IL code for the method
ilGen.Emit(...);

// ...

// Create the type itself
Type newType = typeBuilder.CreateType();
这段代码只是一个示例。它可能包含错误


您也可以在运行时使用System.CodeDom编译C源代码来生成类,但我对此了解不多。

这不是一个奇怪的问题,在某些情况下可能非常有用。例如,我有时使用这种技术进行性能测试:

public static Type[] DynamicTypes;

public void CreateObjects()
{
  var codeNamespace = new CodeNamespace( "DynamicClasses" );
  codeNamespace.Imports.Add( new CodeNamespaceImport( "System" ) );
  codeNamespace.Imports.Add( new CodeNamespaceImport( "System.ComponentModel" ) );

  for( var i = 0; i < 2000; i++ )
  {
    var classToCreate = new CodeTypeDeclaration( "DynamicClass_" + i )
    {
      TypeAttributes = TypeAttributes.Public
    };
    var codeConstructor1 = new CodeConstructor
    {
      Attributes = MemberAttributes.Public
    };
    classToCreate.Members.Add( codeConstructor1 );

    codeNamespace.Types.Add( classToCreate );
  }

  var codeCompileUnit = new CodeCompileUnit();
  codeCompileUnit.Namespaces.Add( codeNamespace );

  var compilerParameters = new CompilerParameters
  {
    GenerateInMemory = true,
    IncludeDebugInformation = true,
    TreatWarningsAsErrors = true,
    WarningLevel = 4
  };
  compilerParameters.ReferencedAssemblies.Add( "System.dll" );

  var compilerResults = new CSharpCodeProvider().CompileAssemblyFromDom( compilerParameters, codeCompileUnit );

  if( compilerResults == null )
  {
    throw new InvalidOperationException( "ClassCompiler did not return results." );
  }
  if( compilerResults.Errors.HasErrors )
  {
    var errors = string.Empty;
    foreach( CompilerError compilerError in compilerResults.Errors )
    {
      errors += compilerError.ErrorText + "\n";
    }
    Debug.Fail( errors );
    throw new InvalidOperationException( "Errors while compiling the dynamic classes:\n" + errors );
  }

  var dynamicAssembly = compilerResults.CompiledAssembly;
  DynamicTypes = dynamicAssembly.GetExportedTypes();
}
公共静态类型[]动态类型;
public void CreateObjects()
{
var codeNamespace=新的codeNamespace(“dynamicclass”);
添加(新的CodeNamespaceImport(“系统”);
添加(新的CodeNamespaceImport(“System.ComponentModel”);
对于(变量i=0;i<2000;i++)
{
var classToCreate=新代码类型声明(“动态类”+i)
{
TypeAttributes=TypeAttributes.Public
};
var codeConstructor1=新的CodeConstructor
{
Attributes=MemberAttributes.Public
};
添加(codeConstructor1);
codeNamespace.Types.Add(classToCreate);
}
var codeCompileUnit=新的codeCompileUnit();
codeCompileUnit.Namespaces.Add(codeNamespace);
var compilerParameters=新的compilerParameters
{
GenerateInMemory=true,
IncludeDebugInformation=真,
TreatWarningAsErrors=真,
警告级别=4
};
compilerParameters.ReferencedAssemblys.Add(“System.dll”);
var compilerResults=new CSharpCodeProvider().CompileAsemblyFromDOM(编译器参数,codeCompileUnit);
if(compilerResults==null)
{
抛出新的InvalidOperationException(“类编译器未返回结果”);
}
if(compilerResults.Errors.HasErrors)
{
var errors=string.Empty;
foreach(CompilerError CompilerError在compilerResults.Errors中)
{
错误+=编译器错误。错误文本+“\n”;
}
调试失败(错误);
抛出新的InvalidOperationException(“编译动态类时出错:\n”+错误);
}
var dynamicAssembly=compilerResults.CompiledAssembly;
DynamicTypes=dynamicAssembly.GetExportedTypes();
}

谢谢,这正是我想要的答案,因为这个答案是经过更多努力才得出的(虽然你们两人都提出了相同的解决方案),所以我担心m rwwilden会将它标记为答案。没问题。我同意这比我自己的答案要详细一点