{ "cells": [ { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "# The `ClockExtension` Sample\n", "\n", "The `ClockExtension` sample walks you through how to create a simple .NET Interactive extension and then package it using NuGet.\n", "\n", "## 1. Build the project\n", "\n", "If you opened this notebook so that its working directory is in the `ClockExtension` project directory, then the following cell will work. Otherwise, you should first switch your working directory to the directory containing this notebook." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "dotnet_interactive": { "language": "pwsh" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "MSBuild version 17.8.3+195e7f5a3 for .NET\n", " Determining projects to restore...\n", " All projects are up-to-date for restore.\n", " ClockExtension -> C:\\dev\\interactive\\samples\\extensions\\ClockExtension\\bin\\Debug\\net8.0\\ClockExtension.dll\n", "\n", "Build succeeded.\n", " 0 Warning(s)\n", " 0 Error(s)\n", "\n", "Time Elapsed 00:00:02.68\n", "MSBuild version 17.8.3+195e7f5a3 for .NET\n", " Determining projects to restore...\n", " All projects are up-to-date for restore.\n", " ClockExtension -> C:\\dev\\interactive\\samples\\extensions\\ClockExtension\\bin\\Release\\net8.0\\ClockExtension.dll\n", "C:\\Program Files\\dotnet\\sdk\\8.0.100\\Sdks\\NuGet.Build.Tasks.Pack\\build\\NuGet.Build.Tasks.Pack.targets(221,5): warning NU5104: A stable release of a package should not have a prerelease dependency. Either modify the version spec of dependency \"microsoft.dotnet.interactive [1.0.0-beta.23562.1, )\" or update the version field in the nuspec. [C:\\dev\\interactive\\samples\\extensions\\ClockExtension\\ClockExtension.csproj]\n", "C:\\Program Files\\dotnet\\sdk\\8.0.100\\Sdks\\NuGet.Build.Tasks.Pack\\build\\NuGet.Build.Tasks.Pack.targets(221,5): warning NU5104: A stable release of a package should not have a prerelease dependency. Either modify the version spec of dependency \"microsoft.dotnet.interactive.csharp [1.0.0-beta.23562.1, )\" or update the version field in the nuspec. [C:\\dev\\interactive\\samples\\extensions\\ClockExtension\\ClockExtension.csproj]\n", " The package ClockExtension.1.0.0 is missing a readme. Go to https://aka.ms/nuget/authoring-best-practices/readme to learn why package readmes are important.\n", " Successfully created package 'C:\\dev\\interactive\\samples\\extensions\\ClockExtension\\bin\\Release\\ClockExtension.1.0.0.nupkg'.\n", "\n", " Directory: C:\\dev\\interactive\\samples\\extensions\\ClockExtension\\bin\\Debug\n", "\n", "\u001b[32;1mMode \u001b[0m\u001b[32;1m LastWriteTime\u001b[0m\u001b[32;1m Length\u001b[0m\u001b[32;1m Name\u001b[0m\n", "\u001b[32;1m---- \u001b[0m \u001b[32;1m -------------\u001b[0m \u001b[32;1m ------\u001b[0m \u001b[32;1m----\u001b[0m\n", "-a--- 12/5/2023 9:34 AM 9220 \u001b[31;1mClockExtension.1.0.0.nupkg\u001b[0m\n", "\n", " Directory: C:\\dev\\interactive\\samples\\extensions\\ClockExtension\\bin\\Release\n", "\n", "\u001b[32;1mMode \u001b[0m\u001b[32;1m LastWriteTime\u001b[0m\u001b[32;1m Length\u001b[0m\u001b[32;1m Name\u001b[0m\n", "\u001b[32;1m---- \u001b[0m \u001b[32;1m -------------\u001b[0m \u001b[32;1m ------\u001b[0m \u001b[32;1m----\u001b[0m\n", "-a--- 12/5/2023 12:37 PM 9192 \u001b[31;1mClockExtension.1.0.0.nupkg\u001b[0m\n", "\n" ] } ], "source": [ "# 1. Build the project\n", "dotnet build ClockExtension\n", "\n", "# Clear any older versions of this extension package from your NuGet cache\n", "rm ~/.nuget/packages/ClockExtension -Force -Recurse -ErrorAction Ignore\n", "\n", "# Pack up the NuGet package. \n", "dotnet pack ClockExtension /p:PackageVersion=1.0.0\n", "\n", "# 3. Check that the package is there\n", "Get-ChildItem -Recurse ClockExtension*.nupkg\n" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "## 2. Load the NuGet package \n", "\n", "Now we're ready to install the extension that packaged up in the NuGet package we just built. We can use the [`#i` directive](https://github.com/dotnet/interactive/blob/main/docs/nuget-overview.md) to add the build output folder to our NuGet sources.\n", "\n", "First, let's make sure the file is there like we expect after the build.\n" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "dotnet_interactive": { "language": "csharp" }, "polyglot_notebook": { "kernelName": "csharp" } }, "outputs": [ { "data": { "text/plain": [ "✅ The package is there!" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "using System.IO;\n", "\n", "// Create an absolute path since #i doesn't like \n", "var debugOutputFolder = new DirectoryInfo(@\".\\ClockExtension\\bin\\Release\\\").FullName;\n", "\n", "if (File.Exists(Path.Combine(debugOutputFolder, \"ClockExtension.1.0.0.nupkg\")))\n", "{\n", " \"✅ The package is there!\".Display();\n", "} \n", "else\n", "{\n", " \"❌ Something must have gone wrong with the build. The package isn't there.\".Display();\n", "}\n", "\n", "var nugetSource = $\"nuget:{debugOutputFolder}\";" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": {}, "source": [ "If the package is there, we can include its location as a NuGet source using the `#i` directive. The following syntax shares the `#i` argument including the `nuget:` prefix and the computed fully-qualified path." ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "dotnet_interactive": { "language": "csharp" }, "polyglot_notebook": { "kernelName": "csharp" } }, "outputs": [ { "data": { "text/html": [ "
ClockExtension
is loaded. It adds visualizations for System.DateTime
and System.DateTimeOffset
. Try it by running: DateTime.Now
or #!clock -h