Marcel: Generierte Klassen zur Laufzeit kompilieren und einbinden.

Guten Morgen,

ich hab ein kleines Problem und komme nicht weiter. Ich habe Klassen in C# zur Laufzeit geschrieben bzw. generiert. Dies sind reine Models und sollen später gefüllt werden. Hier ist der Code zur generierung einer Klasse:

/// <summary>
/// Schreiben einr Klasse mit dazugehörigen Attributen
/// </summary>
/// <param name="className"></param>
/// <param name="attrList"></param>
/// <param name="buildPath"></param>
private static void BuildClass(string className, List<KeyValuePair<string, string>> attrList, string buildPath)
{
    CodeNamespace ns = new CodeNamespace("Validator.Model.Rdf");
    string typeName = className;

CodeTypeDeclaration type = new CodeTypeDeclaration(typeName);

List<CodeMemberProperty> listOfProperty = WritePropertysByAttributeList(attrList);
    foreach (CodeMemberProperty property in listOfProperty)
    {
        type.Members.Add(property);
    }

ns.Types.Add(type);

CSharpCodeProvider provider = new CSharpCodeProvider();
    CodeCompileUnit ccu = new CodeCompileUnit();

ccu.Namespaces.Add(ns);

string classPath = buildPath;
    using (StringWriter writer = new StringWriter())
    {
        provider.GenerateCodeFromCompileUnit(ccu, writer, null);

using (StreamWriter stream = new StreamWriter(classPath + typeName + ".cs"))
        {
            stream.WriteLine(writer.ToString());
        }
    }
}

/// <summary>
/// Attribute als Property definieren.
/// </summary>
/// <param name="listAttribute"></param>
/// <returns></returns>
private static List<CodeMemberProperty> WritePropertysByAttributeList(List<KeyValuePair<string, string>> listAttribute)
{
    List<CodeMemberProperty> listProperty = new List<CodeMemberProperty>();

foreach (KeyValuePair<string, string> attr in listAttribute)
    {
        string name = attr.Key;
        string attrType = attr.Value;

CodeMemberProperty property = new CodeMemberProperty();
        property.Name = name;
        property.Attributes = MemberAttributes.Public;
        property.Type = new CodeTypeReference(typeof(string));
        property.HasGet = true;
        property.HasSet = true;

listProperty.Add(property);
    }

return listProperty;
}

Wie kann ich nun diese Klassen zur Luafzeit kompilieren und in der Laufzeitumgebung verwenden? Weiß das hier jemand?

Vielen Dank und Gruß

Marcel

  1. Moin

    einfach die Stichworte C#, code, compile, runtime in Google einzugeben, hätte dich quasi an erster Stelle auf folgende Seite geführt:

    http://www.codeproject.com/KB/cs/codecompilation.aspx

    Nach kurzem überfliegen muss ich feststellen, dass der Artikel durchaus alles enthalten sollte, wonach du suchst.

    private static void BuildClass(string className, List<KeyValuePair<string, string>> attrList, string buildPath)

    Wozu bitte List<KeyValuePair<string, string>> ?, Warum nicht einfach Dictionary<string, string> ?

    Wie kann ich nun diese Klassen zur Luafzeit kompilieren und in der Laufzeitumgebung verwenden? Weiß das hier jemand?

    Das Kompilat (z.b. Assembly) kannst du (wenn es nicht bereits automatisch geladen ist) mithilfe der Assembly.Load/LoadFrom Methode in die ApplicationDomain laden. Das Benutzen solch dynamischer Dinge ist generell über Reflection machbar (MethodInfo x = Type.GetMethod(...); x.Invoke(targetInstance, ...). Oder du benutzt Interface-Deklarationen und kannst dann darüber ausführen, dann musst du nur den Typ/Klasse mithilfe von Reflection instanzieren. Das geht entweder über den Activator.CreateInstance oder ConstructorInfo.Invoke

    Bitte bedenke, dass solche fetzigen Sachen bei häufiger Benutzung zu erheblichen Performanceeinbrüchen führen können. Ich bin mir fast sicher, dass du dein Ziel auch ohne dynamische Codekompilierung, dafür aber mit entsprechenden Design-Patterns (Bridge, Factory, Composite, Mediator) erreichen kannst.

    Ciao, Frank