Linqpad [Extension] Methods

LINQPad [extension] methods

LINQPad defines two extension methods (in LINQPad.Extensions), namely Dump() and Disassemble(). Dump() writes to the output window using LINQPad's output formatter and is overloaded to let you specify a heading:

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

You can also specify a maximum recursion depth to override the default of 5 levels:

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() disassembles any method to IL, returning the output in a string:

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

In addition to those two extension methods, there are some useful static methods in LINQPad.Util. These are documented in autocompletion, and include:

  • Cmd - executes a shell command or external program
  • CreateXhtmlWriter - creates a text writer that uses LINQPad's Dump() formatter
  • SqlOutputWriter - returns the text writer that writes to the SQL output window
  • GetMyQueries, GetSamples - returns a collection of objects representing your saved queries / samples (for an example, execute a search using Edit | Search All)
  • Highlight - wraps an object so that it will highlight in yellow when Dumped
  • HorizontalRun - lets you Dump a series of objects on the same line

LINQPad also provides the HyperLinq class. This has two purposes: the first is to display ordinary hyperlinks:

new Hyperlinq ("www.linqpad.net").Dump();
new Hyperlinq ("www.linqpad.net", "Web site").Dump();
new Hyperlinq ("mailto:user@domain.example", "Email").Dump();

You can combine this with Util.HorizontalRun:

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

Result:

Check out this site for answers to programming questions.

The second purpose of HyperLinq is to dynamically build queries:

// 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();

You can also write your own extension methods in LINQPad. Go to 'My Queries' and click the query called 'My Extensions'. Any types/methods that define here are accessible to all queries:

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

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

In 4.46(.02) new classes and methods have been introduced:

  • DumpContainer (class)
  • OnDemand (extension method)
  • Util.ProgressBar (class)

Additionally, the Hyperlinq class now supports an Action delegate that will be called when you click the link, allowing you to react to it in code and not just link to external webpages.

DumpContainer is a class that adds a block into the output window that can have its contents replaced.

NOTE! Remember to .Dump() the DumpContainer itself in the appropriate spot.

To use:

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

OnDemand is an extension method that will not output the contents of its parameter to the output window, but instead add a clickable link, that when clicked will replace the link with the .Dump()ed contents of the parameter. This is great for sometimes-needed data structures that is costly or takes up a lot of space.

NOTE! Remember to .Dump() the results of calling OnDemand in the appropriate spot.

To use it:

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

Util.ProgressBar is a class that can show a graphical progressbar inside the output window, that can be changed as the code moves on.

NOTE! Remember to .Dump() the Util.ProgressBar object in the appropriate spot.

To use it:

var pb = new Util.ProgressBar("Analyzing data");
pb.Dump();
for (int index = 0; index <= 100; index++)
{
pb.Percent = index;
Thread.Sleep(100);
}

Using extension method with LinQPad

For starters, you should add System.Data.Entity.Migrations to the LINQPad query's namespace imports (press F4).

Next, you are deluded by the AddOrUpdate method's signature. The first parameter is IDbSet<TEntity>, but that parameter is supplied automatically when you use it as extension method. In context.Rule.AddOrUpdate, it's context.Rule.

If you don't have IDbSet<TEntity>, then you probably didn't connect to an EF6 DbContext.

When using it in a regular static method call (just for academic purposes), it should be

DbSetMigrationsExtensions.AddOrUpdate(context.Rule, y => y.Id, rules);

(where rules, of course, is your collection of rules).

By the way, you could also use context.Rule.AddOrUpdate(rules) because EF used the primary key by default.

LINQPAD - Extension Method to run statement every X seconds

Using Rx, you could do something like this:

Observable.Interval(TimeSpan.FromSeconds(5)).ForEach(_ =>
{
"Hello World".Dump();
});

Consider using a DumpContainer so you don't spam your result window with each and every result.

var container = new DumpContainer().Dump();
var i = 0; // just to show the difference
Observable.Interval(TimeSpan.FromSeconds(5)).ForEach(_ =>
{
container.Content = "Hello World" + i++;
});

How do I use the LINQPad Dump() extension method in Visual Studio?

Look here (your path may vary):

C:\Program Files (x86)\Microsoft Visual Studio 10.0\Samples\1033\CSharpSamples.zip\LinqSamples\ObjectDumper

How to query multiple database names in LinqPad via a global extension method (My Extensions)?

I just found out a workaround that works for me: Refactoring the updated code in the question as follows:

My Extensions

public static class MyExtensions
{
public static List<string> GetAdditionalDatabaseNames<T>(this T userQuery)
{

var props = userQuery.GetType().GetProperties();
var result = new List<string>();
foreach (var db in props.Where(
w => w.PropertyType.Name == "TypedDataContext").Distinct())
{
result.Add(db.Name);
}
return result;
}
}

The difference is, that this time I am not wrapping another extension method around which calls the internal method.

But why does it work? It accepts every kind of object, and since it is using reflection, it doesn't care about the type passed as parameter. The workaround in the question above didn't work because it was trying to cast it into an UserQuery - because the cast doesn't work, it passed null which resulted in the NullReferenceException.

Now you can use it in any query window as mentioned in the example. To get all database names, you can do

Any C# query window

void Main()
{
var dbNames=this.GetAdditionalDatabaseNames(); dbNames.Add(this.Connection.Database);
dbNames.Dump();
}

Note: You might wonder, why this.Connection.Database isn't just added to the list inside the extension method - this is because the Connection object is not accessible inside the My Extensions module.

LINQPad access built-in DataContext in extension methods

I created a static member of type TypedDataSet and "initialize" it in the Main() function with this.

void Main() {

ExtensionMethods.Context = this;
IQueryable<DataContextTable> list = DataContextTables.First().NewMethod(this);

}

public static class ExtensionMethods {

public static TypedDataSet Context;

public static IQueryable<DataContextTable> NewMethod(this DataContextTable table) {
return Context.DataContextTables.Where(item => item.SomeProperty == true);
}

}

How to add Linqpad Extension with existing code

Create a query using your database connection. Set your query mode to Program.

Append the code after the "Define other methods" comment. Add a line to Main to generate the code and output it:

CSharpClassFromSqlGeneratorExtensions.DumpInsert(this.Connection, "SELECT * from Accounts").Dump();

or

CSharpClassFromSqlGeneratorExtensions.DumpClass(this.Connection, "SELECT * from [User]").Dump();

Copy the output into another query.

I don't find the output very useful when I look at it, however.



Related Topics



Leave a reply



Submit