LINQPad [rozszerzenie] metody

144

Czy ktoś ma pełną listę metod i metod rozszerzających LINQPad, takich jak

.Dump()

SubmitChanges()
Bent Rasmussen
źródło
1
Głosuję za zamknięciem tego pytania jako niezwiązanego z tematem, ponieważ LINQPad jest ciągle zmieniającym się narzędziem, a posiadanie solidnej i konkretnej i ostatecznej odpowiedzi na to pytanie będzie miało bardzo krótkie życie. Proponuję zamknąć to jako niezwiązane z tematem, aby uniknąć promowania podobnych pytań w innych narzędziach.
Lasse V. Karlsen
5
Nie mam nic do powiedzenia na temat głosowania, ale na pewno nie zgadzam się z zamknięciem tej odpowiedzi. Najpierw przyjrzyj się głosom za pytanie, a następnie przyjrzyj się głosom za pierwszych dwóch komentarzy. Po drugie, w jaki sposób odpowiedzi Józefa mogą być mniej niż ostateczną odpowiedzią; napisał rzecz. Wreszcie inne aplikacje używają Stackoverflow do tworzenia dokumentacji. Używam LinqPad do programowania przez cały czas, prototypowania zapytań C # i Linq, uruchamiania SQL, wykonywania zadań Quick DBA i dziesiątek innych rzeczy. Tak więc, przynajmniej dla mnie, odpowiedzi są zdecydowanie na temat.
EoRaptor013
3
Ponowne zakończenie: dodałem więcej niż jedną odpowiedź na starsze pytania w C #, aby zapewnić bardziej nowoczesną technikę, która została wprowadzona do języka od czasu odpowiedzi na pytanie. IMO powinniśmy spodziewać się, że baza wiedzy reprezentowana przez tę witrynę będzie modyfikowana i aktualizowana w miarę postępu technologii. Zakres tematów, w których przyszłe aktualizacje mogą zagrozić lub unieważnić odpowiedzi udzielone w określonym momencie, jest dość szeroki: gdybyśmy zamknęli wszystkie pytania, w których może się to zdarzyć, przepełnienie stosu byłoby znacznie gorszym zasobem! Tutaj pełna lista może stać się częściową listą, co jest lepsze niż brak listy!
Bob Sammers

Odpowiedzi:

255

LINQPad definiuje dwie metody rozszerzające (w LINQPad.Extensions), a mianowicie Dump()i Disassemble(). Dump()zapisuje do okna wyjściowego przy użyciu programu formatującego dane wyjściowe LINQPad i jest przeciążony, aby umożliwić określenie nagłówka:

typeof (int).Assembly.Dump ();
typeof (int).Assembly.Dump ("mscorlib");

Możesz również określić maksymalną głębokość rekurencji, aby zastąpić domyślne 5 poziomów:

typeof (int).Assembly.Dump (1);              // Dump just one level deep
typeof (int).Assembly.Dump (7);              // Dump 7 levels deep
typeof (int).Assembly.Dump ("mscorlib", 7);  // Dump 7 levels deep with heading

Disassemble () deasembluje każdą metodę do IL, zwracając wynik w postaci ciągu:

typeof (Uri).GetMethod ("GetHashCode").Disassemble().Dump();

Oprócz tych dwóch metod rozszerzających istnieje kilka przydatnych metod statycznych w LINQPad.Util. Są one udokumentowane w autouzupełnianiu i obejmują:

  • Cmd - wykonuje polecenie powłoki lub program zewnętrzny
  • CreateXhtmlWriter - tworzy moduł zapisujący tekst, który używa programu formatującego Dump () LINQPad
  • SqlOutputWriter - zwraca moduł zapisujący tekst, który zapisuje w oknie danych wyjściowych SQL
  • GetMyQueries , GetSamples - zwraca kolekcję obiektów reprezentujących zapisane zapytania / próbki (na przykład przeprowadź wyszukiwanie za pomocą Edycja | Wyszukaj wszystko)
  • Atrakcja - otacza obiekt tak, że po zrzuceniu będzie podświetlony na żółto
  • HorizontalRun - pozwala zrzucić serię obiektów w tej samej linii

LINQPad udostępnia również klasę HyperLinq. Ma to dwa cele: pierwszym jest wyświetlanie zwykłych hiperłączy:

new Hyperlinq ("www.linqpad.net").Dump();
new Hyperlinq ("www.linqpad.net", "Web site").Dump();
new Hyperlinq ("mailto:[email protected]", "Email").Dump();

Możesz to połączyć z Util.HorizontalRun:

Util.HorizontalRun (true,
  "Check out",
   new Hyperlinq ("http://stackoverflow.com", "this site"),
  "for answers to programming questions.").Dump();

Wynik:

Sprawdź tę witrynę, aby uzyskać odpowiedzi na pytania programistyczne.

Drugim celem HyperLinq jest dynamiczne budowanie zapytań:

// Dynamically build simple expression:
new Hyperlinq (QueryLanguage.Expression, "123 * 234").Dump();

// Dynamically build query:
new Hyperlinq (QueryLanguage.Expression, @"from c in Customers
where c.Name.Length > 3
select c.Name", "Click to run!").Dump();

Możesz również napisać własne metody rozszerzające w LINQPad. Przejdź do „Moje zapytania” i kliknij zapytanie o nazwie „Moje rozszerzenia”. Wszystkie zdefiniowane tutaj typy / metody są dostępne dla wszystkich zapytań:

void Main()
{
  "hello".Pascal().Dump();  
}

public static class MyExtensions
{
  public static string Pascal (this string s)
  {
    return char.ToLower (s[0]) + s.Substring(1);
  }
}

W 4.46 (.02) wprowadzono nowe klasy i metody :

  • DumpContainer (klasa)
  • OnDemand (metoda rozszerzenia)
  • Util.ProgressBar (klasa)

Ponadto klasa Hyperlinq obsługuje teraz Action delegata który będzie wywoływany po kliknięciu łącza, umożliwiając reagowanie na nie w kodzie, a nie tylko jako łącze do zewnętrznych stron internetowych.

DumpContainer to klasa, która dodaje blok do okna wyjściowego, w którym można zamienić jego zawartość.

UWAGA! Pamiętaj, aby.Dump()DumpContainer siebie w odpowiednim miejscu.

Używać:

var dc = new DumpContainer();
dc.Content = "Test";
// further down in the code
dc.Content = "Another test";

OnDemand to metoda rozszerzenia, która nie wyprowadza zawartości swojego parametru do okna wyjściowego, ale zamiast tego dodaje klikalne łącze, które po kliknięciu zastąpi łącze .Dump() treścią ed parametru. Jest to świetne rozwiązanie w przypadku czasami potrzebnych struktur danych, które są kosztowne lub zajmują dużo miejsca.

UWAGA! Pamiętaj o .Dump()wynikach rozmowyOnDemand w odpowiednim miejscu.

Aby z niego skorzystać:

Customers.OnDemand("Customers").Dump(); // description is optional

Util.ProgressBar to klasa, która może wyświetlać graficzny pasek postępu w oknie wyjściowym, który można zmieniać w miarę przesuwania się kodu.

UWAGA! Pamiętaj by.Dump() w odpowiednim miejscu obiekt Util.ProgressBar.

Aby z niego skorzystać:

var pb = new Util.ProgressBar("Analyzing data");
pb.Dump();
for (int index = 0; index <= 100; index++)
{
    pb.Percent = index;
    Thread.Sleep(100);
}
Joe Albahari
źródło
33
Nie ma nic lepszego niż odpowiedź samego autora!
John
1
Joe, tak naprawdę chciałem również stworzyć prototyp niektórych elementów graficznych, a potem chciałem zrzucić bitmapę; byłoby wspaniale z metodą Show dla tego rodzaju pracy, w której potrzebujesz wizualizacji, pracy nad grafiką, obrazem itp. Możliwe, że zapewniasz schludne wizualizacje dla niektórych innych typów w przyszłości.
Bent Rasmussen
... Właściwie, o ile możesz wysłać grafikę do panelu wyjściowego, możemy sami zbudować rozszerzenia dla reszty.
Bent Rasmussen
3
Wersja 4.26 beta pozwala na wstrzyknięcie XHTML do strumienia wyjściowego poprzez wywołanie Util.RawHtml. Przejdź do www.linqpad.net/beta.aspx (lub poczekaj kilka dni na RTM).
Joe Albahari
1
Alex - aby dostać> 1 rzecz na linię, użyj Util.HorizontalRun
Joe Albahari
131

Oprócz dobrze znanej myQuery.Dump("Query result:"), inną cechą, o której warto wspomnieć, jest Utilklasa: zawiera wiele całkiem przydatnych metod (niektóre z nich wspomniałem, ale jest ich o wiele więcej).

Interesujące jest również to, że możesz modyfikować sposób Dump()działania .

Na koniec pokażę ci, jak możesz wprowadzać zmiany na stałe (tj. Wstawiać, aktualizować, usuwać zapytania LINQ) za pomocą SubmitChanges()lubSaveChanges() a także jak uzyskać dostęp do wewnętrznego obiektu połączenia LinqPad.

Podsumowując, pokażę Ci, jak możesz stworzyć prostą grafikę 2D wewnątrz LinqPada (rysowanie linii, bitmap lub funkcji ).

Oto zbiór wbudowanych funkcji LinqPad (z mojego własnego doświadczenia z narzędziem):


.Wysypisko()

(parametry dostępne w LinqPad v5.03.08 i nowszych)

Wszyscy użytkownicy LinqPad znają i uwielbiają .Dump() metodę rozszerzenia, która zużywa i drukuje (prawie) wszystko.

Ale czy wiesz, że dostępnych jest kilka parametrów? Spójrz na ten fragment kodu:

var obj=new { a="Hello", b=5, c="World", d=new { y=5, z=10 } };
obj.Dump(description: "1st example", depth: 5, toDataGrid: false, exclude: "b,d");
obj.Dump("2nd example", exclude: "a,c");
obj.Dump("2nd example", exclude: "+b,d"); // new in V5.06.06 beta

W 1-ci przykład drukuje tylko zmienne ai coraz skór bi dThe 2-ci przykładowe nie odwrotnie (zauważ, że określa ona tylko 2 z dostępnych parametrów). Zmienne yi znie mogą być ukryte pojedynczo, ponieważ nie znajdują się na najwyższym poziomie.

Dostępne są następujące parametry ( wszystkie są opcjonalne ):

  • description [string] - zawiera opis obiektu do zrzutu
  • depth [int?] - ogranicza głębokość rekurencyjnej inspekcji obiektów
  • toDataGrid [bool] - jeśli prawda, dane wyjściowe są formatowane jako datagrid, a nie jako RichText
  • exclude[string] - jeśli podasz listę zmiennych oddzielonych przecinkami, zostaną one wykluczone z wyniku (w przykładzie „a, c”: bi dsą wyświetlane, aac są ukryte)
  • exclude[string] z prefiksem „+” - prefiks odwraca logikę parametru wykluczenia. Oznacza to, że jeśli podasz listę zmiennych oddzielonych przecinkami, wszystkie poza określonymi są ukryte (w przykładzie „+ b, d”: bid są wyświetlane, a wszystkie inne są ukryte)
  • przechowuj włączone i wykluczone właściwości w zmiennej (nowość od LinqPad V5.09.04):
    var x=Util.ToExpando(obj, "a, c", "b, d"); x.Dump();
    pierwszy ciąg zawiera listę właściwości do uwzględnienia, drugi ciąg listę do wykluczenia
  • rozwiń po kliknięciu: jeśli użyjesz .OnDemand("click me").Dump();zamiast .Dump(), wyświetli się link, który możesz kliknąć, aby rozwinąć. Przydatne, jeśli chcesz sprawdzić wartości, np. Util.OnDemand("Customer-ID: " + customerObject.ID.ToString(), ()=>customerObject, false).Dump();Aby zawsze pokazywać ID domyślnie, ale ujawniać szczegóły customerObjecttylko wtedy, gdy jesteś zainteresowany.

Bardziej zaawansowane tematy dotyczące zrzutu można znaleźć tu i tam .


Środowisko

To nie jest rozszerzenie LinqPad, ale raczej klasa .NET, ale ponieważ jest przydatne, i tak o tym wspomnę. Możesz uzyskać wiele przydatnych informacji, których możesz użyć w swoich skryptach, takich jak:

Environment.UserDomainName.Dump();
Environment.MachineName.Dump();
Environment.UserName.Dump();
Environment.CurrentDirectory.Dump();
Environment.SystemDirectory.Dump();

NB Do uzyskania Domain\UserNameużyłbym System.Security.Principal.WindowsIdentity.GetCurrent().Name
raczej niż Environment.UserDomainName+@"\"+Environment.UserName.


Util.WriteCsv

( nowe: dostępne od wersji LinqPad v4.45.05 (beta) )

Util.WriteCsv (Customers, @"c:\temp\customers.csv");

Spowoduje to zapisanie zawartości tabeli Customersdo pliku CSV c:\temp\customers.csv. Możesz również znaleźć dobry przykład, jak używać, Util.WriteCsva następnie wyświetlać dane CSV w oknie wyników Linqpada tutaj .

Poradnik:

  • Aby pobrać / utworzyć plik CSV, który znajduje się w tym samym katalogu co zapytanie, możesz użyć:
    var csvFile=Util.CurrentQueryPath.Replace(".linq", ".csv");

  • Jeśli tabela jest duża, użyj jej ObjectTrackingEnabled = false;przed napisaniem pliku CSV, aby uniknąć buforowania go w pamięci.

  • Jeśli chcesz wyprowadzić tabelę w formacie XML, a nie jako plik rozdzielany przecinkami, możesz to zrobić w następujący sposób:

    var xmlFile=Util.CurrentQueryPath.Replace(".linq", ".xml");
    var xml = XElement.Load(xmlFile);
    var query =
      from e in xml.Elements()
      where e.Attribute("attr1").Value == "a"
      select e;
    query.Dump();

    Ten przykład zwraca wszystkie elementy mające atrybut, attr1który zawiera wartość "a"z pliku XML, który ma taką samą nazwę jak zapytanie i jest zawarty w tej samej ścieżce. Sprawdź ten link, aby uzyskać więcej przykładów kodu.


Util.GetPassword

var pwd = Util.GetPassword("UserXY");

Spowoduje to pobranie hasła z wbudowanego menedżera haseł LinqPad. Aby utworzyć i zmienić hasło, otwórz pozycję menu „Menedżer haseł” w menu „Plik” w LINQPad. Jeśli nie ma zapisanego hasła po uruchomieniu kodu C #, otworzy się okno dialogowe hasła z prośbą o podanie hasła i możesz je utworzyć i zapisać w locie, zaznaczając pole wyboru Zapisz hasło (w tym przykładzie hasło dla "UserXY" zostałby zapisany, a później możesz znaleźć ten wpis w menedżerze haseł ).

Zaletą jest to, że możesz bezpiecznie przechowywać hasło w LinqScripts, które tworzysz w bezpieczny sposób, oddzielnie i zaszyfrowane w profilu użytkownika systemu Windows (jest przechowywane %localappdata%\LINQPad\Passwordsjako plik). LinqPad używa Windows DPAPI do ochrony hasła.

Ponadto hasło jest przechowywane centralnie, więc jeśli chcesz je zmienić, możesz to zrobić w menu i od razu zostanie zastosowane do wszystkich utworzonych skryptów.

Uwagi:

  • Jeśli nie chcesz zapisywać hasła i po prostu wyświetlasz okno dialogowe hasła, możesz użyć drugiego parametru w następujący sposób:
    var pwd = Util.GetPassword("UserXY", true);
    Spowoduje to odznaczenie zapisywania hasła w oknie dialogowym hasła (jednak użytkownik nadal może je sprawdzić i wybierz opcję zapisania mimo wszystko).

  • Jeśli chcesz, aby hasło było przechowywane w a SecureString, możesz użyć tej funkcji pomocniczej (uwaga: aby uzyskać .ToSecureString()używaną metodę rozszerzenia , skorzystaj z tego linku w Stackoverflow - umożliwia ona również konwersję z powrotem w razie potrzeby):
    System.Security.SecureString GetPasswordSecure(string Name, bool noDefaultSave=true)
    {
      return Util.GetPassword(Name, noDefaultSave).ToSecureString();
    }


Util.Cmd

Ta metoda działa jak procesor poleceń. Możesz wywołać wszystkie znane polecenia z konsoli systemu Windows.

Przykład 1 - reż:

Util.Cmd(@"dir C:\");

Spowoduje to wyświetlenie wyniku katalogu bez potrzeby .Dump. Przechowywanie go w zmiennej ma tę zaletę, że można na niej używać dalszych zapytań Linq. Na przykład:

var path=@"C:\windows\system32"; 
var dirSwitch="/s/b";
var x=Util.Cmd(String.Format(@"dir ""{0}"" {1}", path, dirSwitch), true);
var q=from d in x 
        where d.Contains(".exe") || d.Contains(".dll")              
        orderby d
    select d;
q.Dump();

Spowoduje to zrzucenie wszystkich plików z rozszerzeniami „.exe” lub „.dll” zawartych w C:\windows\system32. Plik/sPrzełącznik służy do recurse wszystkie podkatalogi i/b służy do gołej formatu wyjściowego. Należy zauważyć, że drugi parametr metody Cmd jest określony w celu pominięcia danych wyjściowych konsoli, aby wyświetlić tylko przefiltrowany wynik przy użyciu metody Dump.

Jak widzisz, jest to bardziej elastyczne niż posiadane symbole wieloznaczne dir ponieważ możesz wykorzystać pełną elastyczność silnika zapytań Linq.

Przykład 2 - edytor tekstu:

Możesz otworzyć plik w Notatniku w następujący sposób:

var filePath=@"C:\HelloWorld.txt";
Util.Cmd(@"%systemroot%\system32\notepad.exe", filePath);

Util.Image

Wyświetla obrazy z adresu URL. Przykład:

var url = "http://chart.apis.google.com/chart?cht=p3&chd=s:Uf9a&chs=350x140&chl=January|February|March|April";
Util.Image(url).Dump();

Util.ProgressBar, Util.Progress

Użycie Util.ProgressBarumożliwia wyświetlenie paska postępu. Możesz użyć następującej klasy pomocnika:

public class ProgressBar
{
    Util.ProgressBar prog;

    public ProgressBar() 
    { 
        Init("Processing"); 
    }

    private void Init(string msg)
    {
        prog = new Util.ProgressBar (msg).Dump();
        prog.Percent=0;
    }

    public void Update(int percent)
    {
        Update(percent, null);
    }   

    public void Update(int percent, string msg)
    {
        prog.Percent=percent;
        if (String.IsNullOrEmpty(msg))
        {
            if (percent>99) prog.Caption="Done.";
        }
        else
        {
            prog.Caption=msg;
        }
    }
}

Po prostu użyj go, jak pokazuje poniższy przykład:

void Main()
{
    var pb1= new ProgressBar();
    Thread.Sleep(50);
    pb1.Update(50, "Doing something"); Thread.Sleep(550);
    pb1.Update(100); Thread.Sleep(50);
}

Możesz alternatywnie użyć Util.Progressdo aktualizacji zintegrowanego paska postępu LinqPads, na przykład:

Util.Progress = 25; // 25 percent complete

Różnica polega na tym, że nie wyświetli się w oknie wyników i nie możesz przypisać do niego wiadomości.


Util.RawHtml

Wyświetla HTML w oknie wyjściowym. Przykład:

Util.RawHtml (new XElement ("h1", "This is a big heading")).Dump();

Hyperlinq, Util.HorizontalRun

Możesz użyć tej przykładowej funkcji

public void ShowUrl(string strURL, string Title)
{
    Action showURL = delegate() { Process.Start("iexplore.exe", strURL); };
    var url = new Hyperlinq(showURL, "this link", true);
    Util.HorizontalRun (true, "Click ", url, " for details.").Dump(Title);
}

aby pokazać hiperłącza w oknie wyników - lub dowolne działania, takie jak otwarcie ulubionego edytora. Stosowanie:

ShowUrl("http://stackoverflow.com", "Check out StackOverflow");

Zauważ, że ta funkcja zawsze działa, podczas gdy new Hyperlinq ("http://myURL", "Web site").Dump();nie działa w przypadku niektórych adresów URL (szczególnie, jeśli musisz podać nazwy portów, takie jak „: 1234” jako część adresu URL).


Util.ReadLine

Odczytuje dane wejściowe z konsoli. Przykład:

int age = Util.ReadLine<int> ("Enter your age");

Jako synonim słowa Util.ReadLine<string>()możesz również użyć Console.ReadLine().

Ale to nie wszystko! Możesz utworzyć prosty parser JSON za pomocą następującego fragmentu kodu - całkiem przydatne, na przykład, jeśli chcesz przeanalizować i przetestować ciąg JSON w locie. Zapisz następujący fragment kodu jako JSONAnalyzer.linq za pomocą edytora tekstu, a następnie otwórz go w LinqPad (ma to na celu łatwe dodawanie odniesień w locie):

<Query Kind="Program">
    <Reference>&lt;RuntimeDirectory&gt;\System.Web.Extensions.dll</Reference>
    <Namespace>System.Web.Script.Serialization</Namespace>
</Query>

void Main()
{
    var jsonData=Util.ReadLine<string>("Enter JSON string:");
    var jsonAsObject = new JavaScriptSerializer().Deserialize<object>(jsonData);
    jsonAsObject.Dump("Deserialized JSON");
}

Teraz możesz go uruchomić i po prostu wkleić ciąg JSON ze schowka do konsoli - użyje Dumpfunkcji, aby ładnie wyświetlić go jako obiekt - a także otrzymasz komunikaty o błędach parsera na ekranie, aby naprawić problemy. Bardzo przydatne do debugowania AJAX.

JSON


Util.ClearResults

Jeśli chcesz wyczyścić okno wyników w skrypcie, użyj:

Util.ClearResults();

Albo użyj go na górze skryptu, albo - jeśli wykonujesz wiele zapytań w skrypcie - powinieneś poczekać na wejście użytkownika przed wyczyszczeniem ekranu (np. Poprzedzając go Util.ReadLine).


Niestandardowy .Dump () - ICustomMemberProvider

Interesujące jest również to, że możesz zmienić wynik .Dump()metody. Wystarczy zaimplementować interfejs ICustomMemberProvidernp

public class test : ICustomMemberProvider 
{

      IEnumerable<string> ICustomMemberProvider.GetNames() {
        return new List<string>{"Hint", "constMember1", "constMember2", "myprop"};
      }

      IEnumerable<Type> ICustomMemberProvider.GetTypes() 
      {
        return new List<Type>{typeof(string), typeof(string[]), 
            typeof(string), typeof(string)};
      }

      IEnumerable<object> ICustomMemberProvider.GetValues() 
      {
        return new List<object>{
        "This class contains custom properties for .Dump()", 
        new string[]{"A", "B", "C"}, "blabla", abc};
      }

      public string abc = "Hello1"; // abc is shown as "myprop"
      public string xyz = "Hello2"; // xyz is entirely hidden
}

Jeśli utworzysz instancję tej klasy, na przykład

var obj1 = new test();
obj1.Dump("Test");

to będzie tylko wyjście Hint, constMember1, constMember2, i myprop, ale nie właściwość xyz:

Zrzut Linqpad


Wyświetlanie MessageBox lub InputBox w LinqPad

Jeśli chcesz wyświetlić skrzynkę wiadomości, zobacz , jak to zrobić.

Na przykład możesz wyświetlić InputBox przy użyciu następującego kodu

void Main()
{
    string inputValue="John Doe"; 
    inputValue=Interaction.InputBox("Enter user name", "Query", inputValue);
    if (!string.IsNullOrEmpty(inputValue)) // not cancelled and value entered
    {
        inputValue.Dump("You have entered;"); // either display it in results window
        Interaction.MsgBox(inputValue, MsgBoxStyle.OkOnly, "Result"); // or as MsgBox
    }
}

(nie zapomnij nacisnąć F4 i dodać Microsoft.VisualBasic.dll i jego przestrzenie nazw, aby to zadziałało)


Util.Run

( nowe: dostępne od wersji LinqPad v4.52.1 (beta) )

Umożliwia uruchomienie innego skryptu LINQPad z poziomu skryptu lub z własnego programu .NET lub usługi systemu Windows (przez odwołanie do wersji LINQPad4-AnyCPU LINQPad.exe). Wykonuje skrypt tak, jak lprun.exezrobiłoby to narzędzie wiersza poleceń .

Przykłady:

const string path=@"C:\myScripts\LinqPad\";
var dummy=new LINQPad.QueryResultFormat(); // needed to call Util.Run
Util.Run(path+"foo.linq", dummy);

Ten przykład uruchamia skrypt foo.linq, który zawiera następujący przykładowy kod:

void Main(string[] args)
{
    #if CMD
       "I'm been called from lprun! (command line)".Dump();
    #else
       "I'm running in the LINQPad GUI!".Dump();
       args = new[] { "testhost", "[email protected]", "[email protected]", "Test Subject" };
    #endif
    args.Dump("Args");
}

Pozwala sprawdzić, czy skrypt został uruchomiony z poziomu GUI LinqPad lub przez lprun.exelub z Util.Run.

Uwaga: Pomocne mogą być następujące warianty wywołania:

Util.Run(path+"foo.linq", dummy).Dump(); // obviously dumps the script output!
Util.Run(path+"foo.linq", dummy).Save(path+"foo.log"); // writes output into log
Util.Run(path+"foo.linq", dummy).SaveAsync(path+"foo1.log");     // async output log

SubmitChanges () - Linq To SQL

Jeśli używasz LinqToSQL , możesz chcieć wprowadzić zmiany na stałe (dla operacji wstawiania / aktualizowania / usuwania ). Ponieważ kontekst bazy danych jest niejawnie tworzony przez LinqPad, musisz wywołać SubmitChanges()każdą zmianę, jak pokazano poniżej.

Przykłady bazy danych (LinqPad-) Northwind :

Wstawić

var newP = new Products() { ProductID=pID, CategoryID=cID, 
            ProductName="Salmon#"+pID.ToString() };
Products.InsertOnSubmit(newP);
SubmitChanges();    

Aktualizacja

var prod=(from p in Products
            where p.ProductName.Contains("Salmon")
            select p).FirstOrDefault();
prod.ProductName="Trout#"+prod.ProductID.ToString();
SubmitChanges(); 

Usunąć

var itemsToDelete=Products.Where(p=> p.ProductName.Contains("Salmon") ||
    p.ProductName.Contains("Trout"));
foreach(var item in itemsToDelete) { Products.DeleteOnSubmit(item); }
SubmitChanges();

Uwaga: aby uzyskać prawidłowe identyfikatory z poprzednich przykładów, możesz użyć:

var cID = (from c in Categories 
            where c.CategoryName.Contains("Seafood") 
            select c).FirstOrDefault().CategoryID;

var pID = Products.Count()+1;

zanim je przywołasz.


SaveChanges () - Entity Framework

Jeśli używasz Entity Framework , możesz również wprowadzić zmiany na stałe (w przypadku operacji wstawiania / aktualizowania / usuwania ). Ponieważ kontekst bazy danych jest niejawnie tworzony przez LinqPad, musisz wywołać SaveChanges()każdą zmianę, jak pokazano poniżej.

Przykłady są w zasadzie takie same jak wcześniej dla LinqToSQL , ale musisz użyćSaveChanges() , a metody wstawiania i usuwania również się zmieniły.

Wstawić

var newP = new Products() { ProductID=pID, CategoryID=cID, 
            ProductName="Salmon#"+pID.ToString() };
Products.Add(newP);
SaveChanges();  

Aktualizacja

var prod=(from p in Products
            where p.ProductName.Contains("Salmon")
            select p).FirstOrDefault();
prod.ProductName="Trout#"+prod.ProductID.ToString();
SaveChanges(); 

Usunąć

var itemsToDelete=Products.Where(p=> p.ProductName.Contains("Salmon") ||
    p.ProductName.Contains("Trout"));
foreach(var item in itemsToDelete) { Products.Remove(item); }
SaveChanges();

Uwaga: aby uzyskać prawidłowe identyfikatory z poprzednich przykładów, możesz użyć:

var cID = (from c in Categories 
            where c.CategoryName.Contains("Seafood") 
            select c).FirstOrDefault().CategoryID;

var pID = Products.Count()+1;

zanim je przywołasz.


this - kontekst bazy danych

W LINQPad The kontekst baza danych jest stosowana automatycznie za pomocą combobox na górze i wybierając odpowiednią bazę dla Twojego zapytania. Ale czasami warto odwołać się do niego jawnie, na przykład jeśli skopiujesz kod z projektu z programu Visual Studio i wkleisz go do LinqPad.

Twój fragment kodu pobrany z projektu programu Visual Studio najprawdopodobniej wygląda następująco:

var prod=(from p in dc.Products
            where p.ProductName.Contains("Salmon")
            select p).FirstOrDefault();
prod.ProductName="Trout#"+prod.ProductID.ToString();
dc.SaveChanges(); 

Co teraz zrobić dc? Oczywiście możesz usunąć każde wystąpienie dc.w zapytaniu, ale jest to znacznie łatwiejsze. Poprostu dodaj

var dc=this; // UserQuery

na górę fragmentu kodu, na przykład:

void Main()
{
    var dc=this;
    var prod=(from p in dc.Products
                where p.ProductName.Contains("Salmon")
                select p).FirstOrDefault();
    prod.ProductName="Trout#"+prod.ProductID.ToString();
    dc.SaveChanges(); 
}   

a kod zadziała natychmiast!


this.Connection

Korzystanie z LinqPad z OleDb, konwersja obiektu datatable na obiekt Linq, zapytania SQL w Linq

Poniższy fragment kodu ułatwia korzystanie z LinqPad z OleDb. Dodaj System.Data.OleDbz System.Datazestawu do właściwości zapytania, a następnie wklej następujący kod do Main():

var connStr="Provider=SQLOLEDB.1;"+this.Connection.ConnectionString; 

OleDbConnection conn = new OleDbConnection(connStr);
DataSet myDS = new DataSet();
conn.Open();

string sql = @"SELECT * from Customers";
OleDbDataAdapter adpt = new OleDbDataAdapter();
adpt.SelectCommand = new OleDbCommand(sql, conn); 
adpt.Fill(myDS);

myDS.Dump();

Teraz dodaj połączenie SqlServer do LinqPad i dodaj bazę danych Northwind, aby uruchomić ten przykład.

NB: Jeśli chcesz tylko uzyskać bazę danych i serwer aktualnie wybranego połączenia, możesz użyć tego fragmentu kodu:

void Main()
{
    var dc=this;
    var tgtSrv=dc.Connection.DataSource;
    var tgtDb=dc.Connection.ConnectionString.Split(';').Select(s=>s.Trim())
        .Where(x=>x.StartsWith("initial catalog", StringComparison.InvariantCultureIgnoreCase))
        .ToArray()[0].Split('=')[1];
    tgtSrv.Dump();
    tgtDb.Dump();
}

Możesz nawet zamienić myDSna Linq, odpowiedzi na następujące pytanie pokazują, jak to zrobić: Ładne przykłady użycia dynamicznego słowa kluczowego .NET 4 z Linq

Jeszcze jeden przykład: załóżmy, że Twój DBA wysyła zapytanie SQL i chcesz przeanalizować wyniki w LinqPad - oczywiście w Linq, a nie w SQL. Następnie możesz wykonać następujące czynności:

void Main()
{
    var dc=this;

    // do the SQL query
    var cmd =
        "SELECT Orders.OrderID, Orders.CustomerID, Customers.CompanyName,"
        +"       Customers.Address, Customers.City"
        +" FROM Customers INNER JOIN Orders ON Customers.CustomerID = Orders.CustomerID";
    var results = dc.ExecuteQuery<OrderResult>(cmd);

    // just get the cities back, ordered ascending
    results.Select(x=>x.City).Distinct().OrderBy(x=>x).Dump();
}

class OrderResult
{   // put here all the fields you're returning from the SELECT
    public dynamic OrderID=null; 
    public dynamic CustomerID=null;
    public dynamic CompanyName=null;
    public dynamic Address=null;
    public dynamic City=null;
}

W tym przykładzie zapytanie SELECT DBA jest po prostu „wrzucane” do tekstu polecenia, a wyniki są filtrowane i sortowane według miasta.
Oczywiście jest to uproszczony przykład, Twój DBA prawdopodobnie dałby ci bardziej złożony skrypt, ale masz pomysł: po prostu dodaj pomocniczą klasę wyników, która zawiera wszystkie pola z klauzuli SELECT, a następnie możesz jej bezpośrednio użyć .
Możesz nawet pobrać wynik z procedury składowanej w ten sposób i użyć go w Linq. Jak widać, w tym przykładzie nie obchodzi mnie typ danych i używam go dynamicdo wyrażenia.
Tak naprawdę chodzi o szybkie programowanie, aby móc szybko analizować dane. Nie powinieneś tego robić w swojej prawdziwej aplikacji z różnych powodów (iniekcja SQL, ponieważ możesz używać EF od początku itp.).


PanelManager

Narysuj grafikę w LinqPad, część 1

Aby korzystać z przykładów poniżej, naciśnij F4i dodać System.Windows.dll, System.Windows.Forms.dll, WindowsFormsIntegration.dll, PresentationCore.dlli PresentationFramework.dlldo swojego programu LINQPad a także dodać przestrzeń nazw System.Windows.Shapes.

1-ci przykład po prostu rysuje linię:

var myLine = new Line();
myLine.Stroke = System.Windows.Media.Brushes.LightSteelBlue;
myLine.X1 = 1; myLine.X2 = 50;
myLine.Y1 = 1; myLine.Y2 = 50;
myLine.StrokeThickness = 2;
PanelManager.DisplayWpfElement(myLine, "Graphic");

The 2nd przykład pokazuje, jak można wyświetlacz graficzny w LINQPad za pomocą PanelManager. Zwykle LinqPad obsługuje tylko obiekty WPF. W tym przykładzie użyto System.Windows.Forms.Integration.WindowsFormsHostzrobić Windows.Forms.PictureBoxdostępna (to był inspirowany przez to ):

// needs (F4): System.Windows.dll, System.Windows.Forms.dll, 
// WindowsFormsIntegration.dll, PresentationCore.dll, PresentationFramework.dll 
void Main()
{       
    var wfHost1 = new System.Windows.Forms.Integration.WindowsFormsHost();
    wfHost1.Height=175; wfHost1.Width=175; wfHost1.Name="Picturebox1";
    wfHost1.HorizontalAlignment=System.Windows.HorizontalAlignment.Left;
    wfHost1.VerticalAlignment=System.Windows.VerticalAlignment.Top;
    System.Windows.Forms.PictureBox pBox1 = new System.Windows.Forms.PictureBox();
    wfHost1.Child = pBox1;
    pBox1.Paint += new System.Windows.Forms.PaintEventHandler(picturebox1_Paint);
    PanelManager.StackWpfElement(wfHost1, "Picture");
} 

public string pathImg
{
    get { return System.IO.Path.Combine(@"C:\Users\Public\Pictures\Sample Pictures\", 
            "Tulips.jpg"); } 
}

// Define other methods and classes here
public void picturebox1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
    // https://stackoverflow.com/a/14143574/1016343
    System.Drawing.Bitmap bmp = new System.Drawing.Bitmap(pathImg);
    System.Drawing.Point ulPoint = new System.Drawing.Point(0, 0);
    e.Graphics.DrawImage(bmp, ulPoint.X, ulPoint.Y, 175, 175);
}

Stworzy to następującą grafikę (elementy panelu „Grafika” i „Obraz” są dodawane do powyższych przykładów):

Wyświetlam_Graphic_in_LinqPad

Jeśli chcesz wyświetlić obrazy z bazy danych Northwind, możesz wykonać następujące czynności:
Zmień nazwę pliku obrazu na „NorthwindPics.jpg”, a następnie dodaj następujący kod na początku metody Main () w drugim przykładzie :

var img = (from e in this.Employees select e).FirstOrDefault().Photo.ToArray();
using (FileStream fs1 = new FileStream(pathImg, FileMode.Create))
{
    const int offset=78;
    fs1.Write(img, offset, img.Length-offset);
    fs1.Close();
}

Odczyta pierwszy rekord z tabeli Pracownicy i wyświetli obraz.

Sprawdź poniższe łącza, aby dowiedzieć się więcej:
Kształty i podstawowe rysunki w niestandardowych wizualizatorach WPF
LinqPad

Uwaga: możesz osiągnąć to samo bez PanelManagera, co pokazuje poniższy przykład, który tutaj widziałem :

// using System.Drawing;
using (var image=new Bitmap(100, 100))
using (var gr = Graphics.FromImage(image))
{
    gr.FillRectangle(Brushes.Gold, 0, 0, 100, 100);
    gr.DrawEllipse(Pens.Blue, 5, 5, 90, 90);
    gr.Save();
    image.Dump();
}

Używa .Dump()polecenia, aby go wyświetlić. Możesz wywołać image.Dump()wiele razy, a to dołączy obraz.


Windows Forms

Narysuj grafikę w LinqPad, część 2

Poniższy przykład, zainspirowany tym postem, pokazuje, jak zaimplementować prosty ploter funkcyjny w Linqpad 5 przy użyciu C # 7:

void Main()
{
    fnPlotter(x1: -1, x2: 1, fn: (double x) => Math.Pow(x, 3)).Dump();
}

public static Bitmap fnPlotter(double x1=-3, double x2=3, double s=0.05, 
                                   double? ymin=null, double? ymax=null, 
                                   Func<double, double> fn = null, bool enable3D=true)
{
    ymin = ymin ?? x1; ymax = ymax ?? x2;

    dynamic fArrPair(double p_x1 = -3, double p_x2 = 3, double p_s = 0.01, 
                          Func<double, double> p_fn = null)
    {
        if (p_fn == null) p_fn = ((xf) => { return xf; }); // identity as default
        var xl = new List<double>(); var yl = new List<double>();
        for (var x = p_x1; x <= p_x2; x += p_s)
        {
            double? f = null;
            try { f = p_fn(x); }
            finally
            {
                if (f.HasValue) { xl.Add(x); yl.Add(f.Value); }
            }
        }
        return new { Xs = xl.ToArray(), Ys = yl.ToArray() };
    }

    var chrt = new Chart(); var ca = new ChartArea(); chrt.ChartAreas.Add(ca);
    ca.Area3DStyle.Enable3D = enable3D;
    ca.AxisX.Minimum = x1; ca.AxisX.Maximum = x2;   
    ca.AxisY.Minimum = ymin.Value; ca.AxisY.Maximum = ymax.Value;

    var sr = new Series(); chrt.Series.Add(sr);
    sr.ChartType = SeriesChartType.Spline; sr.Color = Color.Red;
    sr.MarkerColor = Color.Blue; sr.MarkerStyle = MarkerStyle.Circle;
    sr.MarkerSize = 2;

    var data = fArrPair(x1, x2, s, fn); sr.Points.DataBindXY(data.Xs, data.Ys); 
    var bm = new Bitmap(width: chrt.Width, height: chrt.Height);
    chrt.DrawToBitmap(bm, chrt.Bounds); return bm;
}

Wykorzystuje możliwości LinqPada do wyświetlania formularzy Windows w panelu wyników. Dodaj referencje (naciśnij ) : , , i dodanie wszystkich nazw tych zespołów.
Przykład
F4
System.Drawing.dllSystem.Windows.Forms.dllSystem.Windows.Forms.DataVisualization.dll


Dodatkowe wskazówki / dalsze czytanie:

  • Chcesz używać LinqPad w programie Visual Studio ? Oto jak możesz to zrobić .

  • Chcesz mieć LinqPad jako „aplikację przenośną” ? Przeczytaj tutaj, jak to zrobić.

  • Witryna Joe dla LinqPad jest zawsze doskonałym źródłem. Wewnątrz LinqPad Help -> What's Newznajdziesz wskazówki dotyczące nowych funkcji i metod. LINQPad Forum zawiera również pomocnych wskazówek.

  • Również bardzo pomocny: ten artykuł o debugowaniu Linq (Pad).

  • Służy lprun.exedo uruchamiania zapytań LINQ w skryptach wsadowych. Przeczytaj ten artykuł, aby uzyskać więcej informacji. Na przykład: w
    echo Customers.Take(100) > script.txt
    lprun -lang=e -cxname=CompanyServer.CustomerDb script.txt
    tym przykładzie zapytanie jest prostym wyrażeniem LINQ. Oczywiście możesz również przygotować złożone zapytania używając -lang=programdo aktywacji trybu programu.

  • Możesz pisać metody rozszerzające i przechowywać je w zakładce Moje zapytania po lewej stronie LinqPad: Ostatni element drzewa nosi nazwę Moje rozszerzenia ; kliknij go dwukrotnie, aby otworzyć plik, w którym możesz zapisać rozszerzenia dostępne dla wszystkich zapytań. Po prostu umieść je w publicznej klasie statycznej MyExtensionsi użyj Main()metody, aby dołączyć testy dla swoich rozszerzeń.

Matt
źródło
2
uwielbiam wskazówkę dotyczącą Util.ReadLine <string> ("Wprowadź jakiś plik json"); Wcześniej kopiowałem to do pliku, a potem czytałem ... Naprawdę uwielbiam tę wskazówkę. Dzięki!
loneshark99
2

Dump jest globalną metodą rozszerzającą, a SubmitChanges pochodzi z obiektu DataContext, który jest obiektem System.Data.Linq.DataContext.

LP dodaje tylko Dump and Disassemble, o ile wiem. Chociaż gorąco polecam otwarcie go w Reflektorze, aby zobaczyć, co jeszcze można użyć. Jedną z bardziej interesujących rzeczy jest przestrzeń nazw LINQPad.Util, która zawiera pewne dodatki używane wewnętrznie przez LINQPad.

Jan
źródło
Uwaga: W nowszych wersjach LinqPad: Kliknij .Dump()lub jakąkolwiek inną metodę w edytorze źródłowym, naciśnij F12, aby „odzwierciedlić”. Jest to teraz wbudowane w narzędzie!
Matt
1

Osiągnąłem limit tekstu StackOverflow w mojej poprzedniej odpowiedzi , ale wciąż jest więcej fajnych rozszerzeń w LinqPad. O jednym z nich chciałbym wspomnieć:


Funkcje JavaScript (używanie .Dump())

Od wersji 5.42 beta LinqPad możesz osadzać funkcje JavaScript i wywoływać je bezpośrednio z kodu C #. Chociaż ma to pewne ograniczenia (w porównaniu z JSFiddle), jest to dobry sposób na szybkie przetestowanie kodu JavaScript w LinqPad.

Przykład:

void Main()
{
    // JavaScript inside C#
    var literal = new LINQPad.Controls.Literal("script",
    @"function jsFoo(x) { 
        alert('jsFoo got parameter: ' + x); 
        var a = ['x', 'y', 'z']; external.log('Fetched \'' + a.pop() + '\' from Stack');
        external.log('message from C#: \'' + x + '\''); 
    }"); 
    // render & invoke
    literal.Dump().HtmlElement.InvokeScript(true, "jsFoo", "testparam");
}

W tym przykładzie funkcja jsFooz jednym parametrem jest przygotowywana i zapisywana w zmiennej literal. Następnie jest renderowany i wywoływany przez .Dump().HtmlElement.InvokeScript(...), przekazując parametr testparam.

Funkcja JavaScript używa external.Log(...)do wyprowadzania tekstu w oknach wyjściowych LinqPad ialert(...) do wyświetlania wyskakującego komunikatu.

Możesz to uprościć, dodając następujące klasy / metody rozszerzenia:

public static class ScriptExtension
{
    public static object RunJavaScript(this LINQPad.Controls.Literal literal, 
                                       string jsFunction, params object[] p)
    {
        return literal.Dump().HtmlElement.InvokeScript(true, jsFunction, p);
    }
    
    public static LINQPad.Controls.Literal CreateJavaScript(string jsFunction)
    {
        return new LINQPad.Controls.Literal("script", jsFunction);
    }
}

Następnie możesz wywołać poprzedni przykład w następujący sposób:

    // JavaScript inside C#
    var literal = ScriptExtension.CreateJavaScript(
    @"function jsFoo(x) { 
        alert('jsFoo got parameter: ' + x); 
        var a = ['x', 'y', 'z']; external.log('Fetched \'' + a.pop() + '\' from Stack');
        external.log('message from C#: \'' + x + '\''); 
    }"); 

    // render & invoke
    literal.RunJavaScript("jsFoo", "testparam");

Ma to ten sam efekt, ale jest łatwiejsze do odczytania (jeśli zamierzasz robić więcej JavaScript ;-)).

Inną opcją, jeśli lubisz wyrażenia lambda i nie lubisz określać nazwy funkcji jako łańcucha za każdym razem, gdy ją wywołujesz, możesz zrobić:

var jsFoo = ScriptExtension.CreateJavaScript(
            @"function jsFoo(x) { ...  }"); 
ScriptExtension.RunJavaScript(() => jsFoo, "testparam");

pod warunkiem, że dodałeś funkcję pomocniczą

public static object RunJavaScript(Expression<Func<LINQPad.Controls.Literal>> expr,  
                                   params object[] p)
{
    LINQPad.Controls.Literal exprValue = expr.Compile()();
    string jsFunction = ((MemberExpression)expr.Body).Member.Name;
    return exprValue.Dump().HtmlElement.InvokeScript(true, jsFunction, p);
}

do klasy ScriptExtension. Spowoduje to rozpoznanie użytej nazwy zmiennej (tutaj jsFoo), która jest tą samą nazwą, co sama funkcja JavaScript (zwróć uwagę, jak wyrażenie lambda jest używane do rozpoznawania nazwy zmiennej, nie można tego zrobić, używając nameof(paramName)wewnątrz funkcji).


.Dump () - aktualizowanie wiadomości w tekście

Czasami warto nadpisać zrzucony tekst , zamiast umieszczać go w nowym wierszu, na przykład, jeśli wykonujesz długotrwałe zapytanie i chcesz pokazać jego postęp itp. (Zobacz także ProgressBar poniżej). Można to zrobić za pomocą pliku DumpContainer, możesz go użyć, jak pokazano w

Przykład 1:

void Main()
{
   var dc = new DumpContainer("Doing something ... ").Dump("Some Action");
   System.Threading.Thread.Sleep(3000); // wait 3 seconds
   dc.Content += "Done.";
}

DumpContainerAnimation

Zwróć uwagę, że w przypadku bardziej złożonych obiektów może być konieczne użycie dc.UpdateContent(obj);zamiast dc.Content=....

Przykład 2:

void Main()
{
    var dc = new DumpContainer().Dump("Some Action");
    for (int i = 10; i >= 0; i--)
    {
        dc.UpdateContent($"Countdown: {i}");
        System.Threading.Thread.Sleep(250);
    };
    dc.UpdateContent("Ready for take off!");
}

Util.ProgressBar

Postęp można również wyświetlić za pomocą ProgressBar w następujący sposób:

Przykład:

void Main()
{
    var prog = new Util.ProgressBar("Processing").Dump();
    for (int i = 0; i < 101; i++)
    {
       Thread.Sleep(50); prog.Percent = i;
    }
    prog.Caption = "Done";
}

Jest to podobne do poprzedniego przykładu zrzutu, ale tym razem pokazuje ładną animację paska postępu.


Testowanie jednostkowe za pomocą LinqPad - xUnit

Czy wiesz, że możesz pisać testy jednostkowe w LinqPad? Na przykład możesz użyć struktury xUnit. Jest dostępny poprzez obsługę NUGET LinqPad - przez F4- w oknie dialogowym kliknij Add NUGET..... Oto opis krok po kroku, jak używać xUnit z LinqPad V5 lub V6.


Jeśli dowiem się więcej, zaktualizuję tę odpowiedź

Matt
źródło