Mechanizm refleksji a przeciążone funkcje

Mechanizm refleksji a przeciążone funkcje
AM
  • Rejestracja:ponad 12 lat
  • Ostatnio:ponad 10 lat
  • Postów:8
0

Witam. Staram się ogarnąć pakiety .NET, mechanizm refleksji, późne wiązanie itp. Stworzyłem sobie pakiet autoIosoba.dll, w pakiecie zawarte są 2 klasy, Auto oraz Osoba. Klasa Auto składa się z tego z czego zazwyczaj składają się klasy, 2 konstruktory, 2 zdarzenia, kilka pól prywatnych i publicznych metod. Dla mojego problemu istotne jest to że w klasie są zdefiniowane 2 wersje metody zwieksz, która ma zwiększyć wartość pola szybkość. Jedna wersja metody jest bez parametru, druga przyjmuje parametr typu int o wartość którego zostanie zwiększona wartość pola szybkość. W nowym projekcie robię coś takiego:

Kopiuj
 
            Assembly autoIosoba = Assembly.Load("autoIosoba");
            Type auto = autoIosoba.GetType("autoIosoba.Auto");
            ConstructorInfo ci = auto.GetConstructor(Type.EmptyTypes);
            Object auto1 = ci.Invoke(new object[] { });
            MethodInfo zwieksz = auto.GetMethod("zwieksz");  //błąd, znaleziono niejednoznaczne dopasowanie
            object[] parameters = null;                   //chcę przykładowo wywołać metodę zwieksz bez parametrów
            zwieksz.Invoke(auto1, parameters);

Zdaję sobie sprawę że błąd powodowany jest przez to że metoda zwieksz jest przeciążona i kompilator nie wie o którą mi chodzi, mimo to nie wiem jak ten problem rozwiązać. Kiedy próbuje wywołać inną metodę, np. wyswietl, wszystko jest w porządku. Co na to poradzić?

somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:dzień
  • Lokalizacja:Wrocław
0

GetMethod po polsku oznacza WeźMetodę. JEDNĄ. Ty masz dwie metody o tej samej nazwie, więc metoda znajdująca jedną, nie ma logicznego prawa zadziałać.
Użyj np. metody GetMethods, która zwróci Ci tablicę MethodInfo i w niej szukaj swojej metody.

edytowany 1x, ostatnio: somekind
AM
  • Rejestracja:ponad 12 lat
  • Ostatnio:ponad 10 lat
  • Postów:8
0

No tak, przeoczyłem to. Dzięki :)

Azarien
  • Rejestracja:ponad 21 lat
  • Ostatnio:9 minut
0

object[] parameters = null; //chcę przykładowo wywołać metodę zwieksz bez parametrów
zwieksz.Invoke(auto1, parameters);

a dlaczego nie

Kopiuj
zwieksz.Invoke(auto1, null);                   //chcę przykładowo wywołać metodę zwieksz bez parametrów
AM
  • Rejestracja:ponad 12 lat
  • Ostatnio:ponad 10 lat
  • Postów:8
0

No tak, oczywiście może być null, na początku tak miałem ale błąd sprawił że w różnych miejscach szukałem rozwiązania i zmieniłem null na pustą tablicę obiektów. Ok, zrobiłem to tak:

Kopiuj
            Assembly autoIosoba = Assembly.Load("autoIosoba");
            Type auto = autoIosoba.GetType("autoIosoba.Auto");
            ConstructorInfo ci = auto.GetConstructor(Type.EmptyTypes);
            Object auto1 = ci.Invoke(new object[] { });
            MethodInfo[] zwieksz = auto.GetMethods();
            MethodInfo zwieksz1 = null;   //do tego pola przypiszę 1 metodę o nazwie zwiększ
            MethodInfo zwieksz2 = null;   //a do tego drugą
            
            foreach (var item in zwieksz)   //przeszukanie tablicy zawierającej wszystkie tablice
            {
                if (item.Name == "zwieksz")
                {
                    if (zwieksz1 == null)  //przypisanie 1 odpowiedniego wyniku do 1 zmiennej
                    {
                        zwieksz1 = item;
                    }
                    else if (zwieksz2 == null)  //przypisanie 2 wyniku do 2 zmiennej
                    {
                        zwieksz2 = item;
                    }
                }
            }
            MethodInfo mojaMetoda = null; //zmienna do której przypiszę właściwą, bezparametrową metodę zwieksz
            ParameterInfo[] parametry1 = zwieksz1.GetParameters();
            ParameterInfo[] parametry2 = zwieksz2.GetParameters();
            if (parametry1.Length == 0)   //sprawdzam czy metoda jest bezparametrowa, takiej wlasnie szukam
            {
                mojaMetoda = zwieksz1;
            }
            else if (parametry2.Length == 0)    //sprawdzam czy metoda jest bezparametrowa, takiej wlasnie szukam
            {
                mojaMetoda = zwieksz2;
            }
            mojaMetoda.Invoke(auto1, null);
            Console.Read(); 

Wszystko ładnie działa. teraz zastanawiam się czy można zrobić to jakoś inaczej, to znaczy ładniej i czytelniej? Może można przeszukać tablicę MethodInfo[] zwieksz zapytaniem LINQ które od razu zwróci metodę zwieksz bez parametrów? A może cel można osiągnąć w jeszcze prostszy sposób?

somekind
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:dzień
  • Lokalizacja:Wrocław
0

Ten kod to jakaś tragedia, gorzej się tego nie dało napisać. Po co tyle zmiennych pomocniczych, pętli i ifów?

Kopiuj
Assembly autoIosoba = Assembly.Load("autoIosoba");
Type auto = autoIosoba.GetType("autoIosoba.Auto");
ConstructorInfo ci = auto.GetConstructor(Type.EmptyTypes);
Object auto1 = ci.Invoke(new object[] { });

// metodą małych kroczków:
// wybieramy wszystkie metody o nazwie "zwieksz"
List<MethodInfo> metodyZwieksz = new List<MethodInfo>();
foreach (MethodInfo mi in auto.GetMethods())
{
    if (mi.Name == "zwieksz")
    {
        metodyZwieksz.Add(mi);
    }
}

// znajdujemy tą bez parametru
MethodInfo metodaBezParametru;
foreach (MethodInfo mi in metodyZwieksz)
{
    if (mi.GetParameters().Length == 0)
    {
        metodaBezParametru = mi;
        break;
    }
}

// lepiej od razu w jednej pętli:
MethodInfo metodaBezParametru2;
foreach (MethodInfo mi in auto.GetMethods())
{
    if (mi.Name == "zwieksz" && mi.GetParameters().Length == 0)
    {
        metodaBezParametru2 = mi;
        break;
    }
}

// albo w LINQ:
var metodaBezParametru3 = auto.GetMethods().SingleOrDefault(q => q.Name == "zwieksz" && q.GetParameters().Length == 0); 
msm
Mogłeś to podzielić na trzy kody, bo na początku myślałem że tyle kodu Ci zajęło napisanie tego (tak, zwątpiłem :< ), dopiero później zobaczyłem ludzkie rozwiązanie w LINQ :>
somekind
Nie mogłem, bo 4 pierwsze linijki są wspólne.
AM
  • Rejestracja:ponad 12 lat
  • Ostatnio:ponad 10 lat
  • Postów:8
0

Dzięki somekind, teraz to ma ręce i nogi.

Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)