Laden...

Fluent CodeDOM

Erstellt von Desert Fox vor 13 Jahren Letzter Beitrag vor 13 Jahren 4.291 Views
D
Desert Fox Themenstarter:in
33 Beiträge seit 2010
vor 13 Jahren
Fluent CodeDOM

Da ich die erstellung von Code via CodeDOM ziemlich umständlich fand und ich mal testen wollte was man mit einer .NET sprache so alles anstellen kann hab ich mal diese kleine Libary geschrieben.

Fluent CodeDOM Auf Codeplex

Würde mich freuen wenn Ihr mir ein bisschen Feedback drüber geben könntet, ist meine erste Libary die ich wirklich veröffentlicht habe.

I
279 Beiträge seit 2008
vor 13 Jahren

Hehe irgendwie cool ^^

742 Beiträge seit 2005
vor 13 Jahren

Sieht super aus, die API könnte man aber noch verbessern:

  • Ist das .Body wirklich nötig
  • Könnte man CallStatic nicht vereinfachen, damit das Expr.Primitive unnötig wird? (z.B. objekt array als Argumente, alle nicht-expressions werden in ein primitive umgewandelt).

Ich denke da gibts noch viel Potential, die Idee finde ich aber Klasse und werde es auch verwenden, sobald ich wieder was mit CodeDOM mache.

D
Desert Fox Themenstarter:in
33 Beiträge seit 2010
vor 13 Jahren

Danke für das Feedback, bei !!! 4 !!! downloads muss ich echt noch was tun das die libary bekannter wird

Das CallStatic vereinfachen hab ich mir auch schon gedacht denke ich werde ich einbauen.

Das Body habe ich eingebaut damit man nicht wild Parameter Rückgabetyp und Code Vermischt. Was ich aber schon länger überlege das man nur noch ein End nach einem methoden body machen soll also statt


.Method(MemberAttributes.Public | MemberAttributes.Static, "Main").Parameter(typeof(string[]), "args")
.Body
	.CallStatic(typeof(Console), "WriteLine", Expr.Primitive("Hello Fluent CodeDom"))
.End.End

nur noch schreiben muss


.Method(MemberAttributes.Public | MemberAttributes.Static, "Main").Parameter(typeof(string[]), "args")
.Body
	.CallStatic(typeof(Console), "WriteLine", Expr.Primitive("Hello Fluent CodeDom"))
.End

Man kann das Body und das End ja als scopes sehen oder wie in TSQL das BEGIN und END Statement

49.485 Beiträge seit 2005
vor 13 Jahren

Hallo Desert Fox,

zumindest sollte intuitiv klar sein, wo man End setzen muss. Für Parameter braucht man ja auch kein End. Weshalb sollte man es dann für Method brauchen? Überhaupt ist es schwer einem Namen wie Method, Parameter oder Body anzusehen, ob er nun ein End braucht oder nicht.

Klarer wäre es, wenn man End nur dort braucht, wo man vorher Begin verwendet hat. Also dass man quasi genau da Begin/End verwendet, wo man in normalem Code eine öffnende/schließende geschweifte Klammer setzt.

Wenn dir Begin und End nicht sprechend genug sein sollten, könntest du BeginBody und EndBody verwenden. Aber Body und End sind irgendwie asymmetrische Bezeichnungen.

herbivore

742 Beiträge seit 2005
vor 13 Jahren

Sehe ich genauso, mein Wunsch Syntax wäre:


.Method(MemberAttributes.Public | MemberAttributes.Static, "Main")
    .Parameter(typeof(string[]), "args1")
    .Parameter(typeof(string[]), "args2")
.BeginBody
    .CallStatic(typeof(Console), "WriteLine", Expr.Primitive("Hello Fluent CodeDom"))
    .CallStatic(typeof(Console), "WriteLine", Expr.Primitive("Hello Again"))
.EndBody

D
Desert Fox Themenstarter:in
33 Beiträge seit 2010
vor 13 Jahren

Also persönlich würde ich dann doch

Begin
End

bevorzugen EndBody ist mir dann doch zuviel Text

Hmm über eine VB ähnliche syntax habe ich auch schon nachgedacht und immoment muss ich doch sagen das eine syntax wie


.Method("Test").Parameter(typeof(int) "i")
      .CallStatic(typeof(Console), "WriteLine", "Test")
.EndMethod

doch auch am meisten zusagen würde und das mit dem Body weglassen könnte zwar zu ner ziemlich scheuslichen syntax führen, für den well formed code ist dann am ende der programmierer ja eh selbst verantwortlich.

Wenn man nur End Verwendet habe ich selbst schon gemerkt das man da schnell mit den Ends Durcheinander kommt. Und so schlecht schaut das dann garnicht aus


                .Namespace("Test.FluentCodeDom.Test")
                    .Import("System")
                    .Import("System.Text")

                    .Class(MemberAttributes.Public, "StringModifier")
                        .Field(typeof(int), "_intValue").EndField
                        .Property(MemberAttributes.Public, typeof(int), "IntValue")
                            .Get
                                .Return(Expr.Var("_intValue"))
                            .EndGet
                            .Set
                                .Set(Expr.Var("_intValue"), Expr.Value())
                            .EndGet
                        .EndProperty
                    .EndClass
                .EndNamespace

D
Desert Fox Themenstarter:in
33 Beiträge seit 2010
vor 13 Jahren

Also ich bin grade dabei das ganze umzustellen wie im post oben gezeigt, man muss aber sagen das ganze nicht umbedingt ganz einfach da ich schon ziemlich extremes zeug mit Generics mache.
(Man kann sich ja mal den source anschauen, das ist problem ist nämlich das auch so sachen wie Ifs in Schleifen in Try Blöcken in Methoden möglich sein müssen)
und dann kommen halt mal fehlermeldungen wie die hier raus:

Fehlermeldung:
Fehler 2 "FluentCodeDom.FluentCodeBody <FluentCodeDom.FluentCodeBody <FluentCodeDom.FluentCodeType <FluentCodeDom.FluentCodeClass>, FluentCodeDom.FluentCodeMethod <FluentCodeDom.FluentCodeClass>>, FluentCodeDom.FluentCodeBody <FluentCodeDom.FluentCodeBody <FluentCodeDom.FluentCodeType <FluentCodeDom.FluentCodeClass>, FluentCodeDom.FluentCodeMethod <FluentCodeDom.FluentCodeClass>>, FluentCodeDom.FluentCodeBody <FluentCodeDom.FluentCodeType <FluentCodeDom.FluentCodeClass>, FluentCodeDom.FluentCodeMethod <FluentCodeDom.FluentCodeClass>>.IfCodeBody>.ElseCodeBody>" enthält keine Definition für "EndIf", und es konnte keine Erweiterungsmethode "EndIf" gefunden werden, die ein erstes Argument vom Typ "FluentCodeDom.FluentCodeBody <FluentCodeDom.FluentCodeBody <FluentCodeDom.FluentCodeType <FluentCodeDom.FluentCodeClass>, FluentCodeDom.FluentCodeMethod <FluentCodeDom.FluentCodeClass>>, FluentCodeDom.FluentCodeBody <FluentCodeDom.FluentCodeBody <FluentCodeDom.FluentCodeType <FluentCodeDom.FluentCodeClass>, FluentCodeDom.FluentCodeMethod <FluentCodeDom.FluentCodeClass>>, FluentCodeDom.FluentCodeBody <FluentCodeDom.FluentCodeType <FluentCodeDom.FluentCodeClass>, FluentCodeDom.FluentCodeMethod <FluentCodeDom.FluentCodeClass>>.IfCodeBody>.ElseCodeBody>" akzeptiert. (Fehlt eine Using-Direktive oder ein Assemblyverweis?) C:\Daten\Projects\Dropbox\Nation Commander\FluentCodeDom\FluentCodeDom.Test\DeclarationTests.cs 66 30 FluentCodeDom.Test

D
Desert Fox Themenstarter:in
33 Beiträge seit 2010
vor 13 Jahren

Also habe das ganze jetzt geupdated und die neue version ist auf codeplex verfügbar.

Changes sind somit:

  • Body Element nciht mehr nötig
  • Alles wird jetzt anstelle von End mit EndMethod, EndIf etc. beendet
  • Interne Klassenstruktur vereinfacht.

Mir ist bewusst das aller alte code der damit erstellt wurde geupdated werden muss bei 7 downloads ist das aber denke ich mal zu verkraften ^^

Das ganze sieht jetzt wie oben angekündigt so aus:


namespace FluentCodeDom.Sample1
{
    class Program
    {
        static void Main(string[] args)
        {
            CodeCompileUnit compileUnit = new FluentCodeCompileUnit()
                .Namespace("Sample1")
                    .Class("Program")
                        .Method(MemberAttributes.Public | MemberAttributes.Static, "Main").Parameter(typeof(string[]), "args")
                            .CallStatic(typeof(Console), "WriteLine", Expr.Primitive("Hello Fluent CodeDom"))
                        .EndMethod
                    .EndClass
                .EndNamespace
            .EndFluent();

            Assembly assembly = Helper.CodeDomHelper.CompileInMemory(compileUnit);
            assembly.GetType("Sample1.Program").GetMethod("Main").Invoke(null, new object[] { null });
        }
    }
}