我要问一个可能听起来很奇怪的问题。
有没有办法在运行时创建一个新的类?或者至少向现有类添加一个新属性。
我的意思是创建一个不存在的类,而不是现有类的实例。稍后我可以使用反射来加载和使用这个类。
发布于 2009-05-30 09:02:28
无法向现有类型添加属性,但可以在运行时使用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#源代码来生成类,但我对此了解不多。
发布于 2009-05-30 08:43:24
看一下System.Reflection.Emit名称空间。我自己从来没有用过它,但是这个名称空间中的类可以用来生成IL (中间语言)。
发布于 2009-05-30 09:04:13
这并不是一个奇怪的问题--在某些情况下,它可能非常有用。例如,我有时会使用此技术进行性能测试:
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();
}
https://stackoverflow.com/questions/929349
复制相似问题