Laden...

Per Expression Methode übergeben und ausführen

Erstellt von Quaneu vor 8 Jahren Letzter Beitrag vor 8 Jahren 1.667 Views
Quaneu Themenstarter:in
692 Beiträge seit 2008
vor 8 Jahren
Per Expression Methode übergeben und ausführen

Hallo zusammen,

ich würde gern per Expression eine Methode übergeben und diese dann auch ausführen lassen.

Z.B.


public sealed class A
{
    public void Do<T>(Expression<Action<T>> expression)
    {
        // hier soll ToCall aufgerufen werden!!!
    }
}

public sealed class B
{
    public void Method()
    {
        A test = new A();
        test.Do<B>(x => x.ToCall());
    }

    private void ToCall()
    { }
}


Ich schaffe es leider nicht ohne weiteres ToCall in Do aufzurufen. Bisher schaffe ich es nur, wenn ich ein Delegate erzeuge und diesen dann aufrufe. Jetzt wollte ich fragen, ob es nicht einen leichteren Weg gibt, da ja in der Expression eigentlich schon alle Infos stecken. Wenn jemand eine Idee hat, wäre ich sehr dankbar 😃.

Schöne Grüße
Quaneu

127 Beiträge seit 2015
vor 8 Jahren

Verstehe nicht ganz wozu dieses A / B Klassen Konstrukt gut sein soll und warum du eine Expression verwendest.

Aber ein Weg wie es so funktioniert wie du es beschreibst:


public sealed class A
    {
        public void Do<T>(Action expression)
        {
            // hier soll ToCall aufgerufen werden!!!
            expression.Invoke();
        }
    }

    public sealed class B
    {
        public void Method()
        {
            A test = new A();
            test.Do<B>(ToCall);
        }

        private void ToCall()
        { }
    }
Quaneu Themenstarter:in
692 Beiträge seit 2008
vor 8 Jahren

Hallo hummigbird1,

dies sollte nur als Beispiel dienen. Ich weiß, dass dieses Beispiel nicht gerade viel Sinn macht 😃, aber ich wollte es so einfach wie möglich halten.
Es muss eine Expression sein, da ich damit jede Methode "darstellen" kann. Z.B. kann ich leider mit deinem Ansatz ToCall nicht aufrufen, wenn diese ein out oder ref Parameter besitzt.

ToCall kann eine beliebige Funktion sein. Hatte ich vergessen zu sagen, Sorry. Z.B. eben auch:


private int ToCall<T>(int a, T b, out double c, ref float d)
{
	c = 1.2d;
	d = 4.6f;
	return a + 1;
}

Schöne Grüße
Quaneu

127 Beiträge seit 2015
vor 8 Jahren

So würde das Beispiel von dir funktionieren.
In den Body der anonymem Methode (die als Action Parameter der Do Methode übergeben wird) kannst du reinschreiben was du willst.

Aber vermutlich habe ich immer noch nicht ganz verstanden welchen Umfang das ganze annehmen können soll oder wozu das ganze dienen soll.


public sealed class A
    {
        public void Do<T>(Action expression) 
        {
            // hier soll ToCall aufgerufen werden!!!
            expression.Invoke(); 
        }
    }

    public sealed class B
    {
        public void Method()
        {
            A test = new A();
            double dOut; // Beispiel 
            float fRef = 0f; // Beispiel 
            test.Do<B>(delegate() { ToCall<int>(1, 2, out dOut, ref fRef); });
        }

        private int ToCall<T>(int a, T b, out double c, ref float d)
        {
            c = 1.2d;
            d = 4.6f;
            return a + 1;
        }
    }

Quaneu Themenstarter:in
692 Beiträge seit 2008
vor 8 Jahren

Vielen Dank, das sieht schon einfacher aus 😄. Jedoch ist es für den User wieder nicht ganz so schön. Daher würde es mir am Besten mit der Expression gefallen, da es leichter für den User ist. Ich hatte gehofft das ich über die Expression auch an z.B. die Action komme und sie invoken kann.

Ich will einer Klasse mitgeben, was passieren soll, wenn eine bestimmte Methode einer anderen Klasse aufgerufen wird. Dazu muss ich ihr eben mitteilen um welche Methode es sich handelt und was er machen soll, wenn diese aufgerufen wird.

2.079 Beiträge seit 2012
vor 8 Jahren

Die delegate-Variante von hummigbird1 geht auch kürzer so:

test.Do<B>(() => ToCall<int>(1, 2, out dOut, ref fRef));

In meinen Augen ist das völlig ausreichend, noch übersichtlicher wirst Du es nicht hin bekommen.

Wenn Du aber unbedingt Expressions nutzen willst:

public void Do<T>(Expression<Action<T>> expression)
{
    expression.Compile().Invoke();
}

Der einzige Sinn, den ich bei Expressions sehe, ist der, dass man die Expression bzw. den Aufbau und die enthaltenen Elemente analysieren kann. Ich kann mir die Reflection-Informationen zu jedem enthaltenen Element ausgeben lassen und das ist bedeutend schneller als Reflection.

Z.B. Bei dem EntityFramework wird das im Zusammenhang mit LINQ genutzt. IQueryable bietet die gleichen Erweiterungsmethoden an, wie IEnumerable, baut intern aber eine komplexe Expression zusammen, mit der dann der IQueryProvider ein SQL-Statement erstellen kann.

Rein Optisch hat das aber keinen Vorteil, es schränkt den Aufruf sogar ein, denn als Expression-Parameter sind nur Lambda-Ausdrücke erlaubt. Man kann keine Methoden oder komplexere anonyme Methoden übergeben. Dafür muss der Parameter-Typ der reine Delegate sein.

NuGet Packages im Code auslesen
lock Alternative für async/await

Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.

Quaneu Themenstarter:in
692 Beiträge seit 2008
vor 8 Jahren

Hallo Palladin007,

vielen Dank (natürlich auch Dir hummigbird1 😉). Das funktioniert super. Ich dachte ich hätte das gestern auch probiert und es hat nicht geklappt 8o...
Da ich die Elemente auch analysieren muss werde ich wohl bei der Expression bleiben. Wobei ich ich nur den RückgabeTyp und die ParameterTypen prüfen muss. Diese Informationen habe ich auch in der Action. D.h. ich probiere es doch einmal mit der Action.

Schöne Grüße
Quaneu