Если я понимаю, что вы хотите, кажется, у вас есть 2 варианта:
- используйте CodeDOM для генерации и динамической компиляции кода во время выполнения.
- испускает реальный исходный код C # и динамически компилирует его в вызываемую сборку во время выполнения.
CodeDom - это какой-то волосатый код очень низкого уровня для написания. Идея в том, что есть объектная модель для языка C #. Вы начинаете с создания экземпляра CodeTypeDeclaration - это сгенерирует тип или класс. Затем вы добавляете свойства и поля - здесь вы, скорее всего, добавите объявления DllImport
для ваших функций p / invoke. Затем вы используете разные методы добавления CodeDOM для типа - это будет то место, куда вы вставите сгенерированный метод. Вы можете сделать это публичным, статичным, что угодно.
CodeDOM выглядит так:
System.Type mt= a[0].GetType();
System.CodeDom.CodeTypeDeclaration class1 = new System.CodeDom.CodeTypeDeclaration(mt.Name);
class1.IsClass=true;
class1.TypeAttributes = System.Reflection.TypeAttributes.Public;
class1.Comments.Add(new System.CodeDom.CodeCommentStatement("Wrapper class for " + mt.Name));
System.CodeDom.CodeConstructor ctor;
ctor= new System.CodeDom.CodeConstructor();
ctor.Attributes = System.CodeDom.MemberAttributes.Public;
ctor.Comments.Add(new System.CodeDom.CodeCommentStatement("the null constructor"));
class1.Members.Add(ctor);
ctor.Statements.Add(new System.CodeDom.CodeAssignStatement(new System.CodeDom.CodeVariableReferenceExpression("m_wrapped"), new System.CodeDom.CodeObjectCreateExpression(mt)));
ctor= new System.CodeDom.CodeConstructor();
ctor.Attributes = System.CodeDom.MemberAttributes.Public;
ctor.Comments.Add(new System.CodeDom.CodeCommentStatement("the 'copy' constructor"));
class1.Members.Add(ctor);
ctor.Parameters.Add(new System.CodeDom.CodeParameterDeclarationExpression(mt,"X"));
ctor.Statements.Add(new System.CodeDom.CodeAssignStatement(new System.CodeDom.CodeVariableReferenceExpression("m_wrapped"), new System.CodeDom.CodeVariableReferenceExpression("X")));
// embed a local (private) copy of the wrapped type
System.CodeDom.CodeMemberField field1;
field1= new System.CodeDom.CodeMemberField();
field1.Attributes = System.CodeDom.MemberAttributes.Private;
field1.Name= "m_wrapped";
field1.Type=new System.CodeDom.CodeTypeReference(mt);
class1.Members.Add(field1);
...
это продолжается. и вкл. Как видите, это становится довольно уродливо. Затем вы компилируете его, чего я не показал. Я предполагаю, что вы не захотите использовать этот подход.
Я нашел CodeDom довольно хитрым в использовании; вместо этого теперь, когда мне нужны динамически сгенерированные сборки, я испускаю фактический код C # , обычно через шаблоны, в строку в памяти и скомпилирую , что . Это намного проще для моих целей. Компиляция выглядит так:
var cp = new System.CodeDom.Compiler.CompilerParameters {
ReferencedAssemblies.Add(filesystemLocation), // like /R: option on csc.exe
GenerateInMemory = true, // you will get a System.Reflection.Assembly back
GenerateExecutable = false, // Dll
IncludeDebugInformation = false,
CompilerOptions = ""
};
var csharp = new Microsoft.CSharp.CSharpCodeProvider();
// this actually runs csc.exe:
System.CodeDom.Compiler.CompilerResults cr =
csharp.CompileAssemblyFromSource(cp, LiteralSource);
// cr.Output contains the output from the command
if (cr.Errors.Count != 0)
{
// handle errors
}
System.Reflection.Assembly a = cr.CompiledAssembly;
// party on the type here, either via reflection...
System.Type t = a.GetType("TheDynamicallyGeneratedType");
// or via a wellknown interface
В приведенном выше коде LiteralSource
содержит исходный код для компиляции. Как я уже сказал, я генерирую это, читая шаблон и заполняя пробелы.