OpenAI und Visual Studio Extension

Als kleine Fingerübung dachte ich mir, dass eine Visual Studio Extension gut wäre die Code erklärt – dank OpenAI sollte das ja kein Problem sein.

War es auch nicht.

Zuerst installierte ich das Extensibilty Template Pack 2022 für Visual Studio 2022.
Danach konnte es beginnen:

Als erstes fügte ich ein Tool Window hinzu. Ein Toolwindow ist im Prinzip nichts anderes als eine XAML User control und eine Klasse die von BaseToolWindow ableitet

  public class ExplicareToolWindow : BaseToolWindow<ExplicareToolWindow>
    {
        public override string GetTitle(int toolWindowId) => "Explicare";

        public override Type PaneType => typeof(Pane);

        public override async Task<FrameworkElement> CreateAsync(int toolWindowId, CancellationToken cancellationToken)
        {

           var dte = await Package.GetServiceAsync(typeof(EnvDTE.DTE)) as EnvDTE80.DTE2;

            return new ExplicareToolWindowControl(dte,Package);
        }

        [Guid("b8381bcb-59d1-4b5c-9951-fdbfb44990c9")]
        internal class Pane : ToolWindowPane
        {
            public Pane()
            {
                BitmapImageMoniker = KnownMonikers.ToolWindow;
            }
        }
    }

ExplicareToolWindowControl(dte,Package); ist die eigentliche UserControl – in der wir beliebige UI Elemente einbauen können.
Ich habe jetzt nur einen Button eingebaut den ich „Explain to me“ genannt habe.
Schnell und Schmutzig im Code-Behind ein Button Click Event gemacht.
Nun den Text aus dem Visual Studio Editor auslesen dies geschieht mit:

 var textSelection = (TextSelection)MyDTE.ActiveDocument.Selection;

                if (String.IsNullOrEmpty(textSelection.Text))
                {
                    TextDocument doc = (TextDocument)(MyDTE.ActiveDocument.Object("TextDocument"));

                    var p = doc.StartPoint.CreateEditPoint();
                    TextToExplain = p.GetText(doc.EndPoint);

                }
                else
                {
                    TextToExplain = textSelection.Text;

                }

So das schwierigste habe ich hinter mir nun noch einen Aufruf des OpenAI API aufrufen. Das geht eigentlich ganz einfach

  var content = new StringContent(jsonContent, Encoding.UTF8, "application/json");


                var response = client.PostAsync("https://api.openai.com/v1/completions", content).Result;
                if (response.IsSuccessStatusCode)
                {
                    string responseStr = await response.Content.ReadAsStringAsync();

                    var result = JsonConvert.DeserializeObject<OpenAIResponse>(responseStr);
                    explained = result.choices[0].text;
                }
                else
                {
                    throw new BadRequestExecption();
                }

Den ganzen Source ist auf Git Hub gpiwonka/Explicare: A small extension for Visual Studio to better understand code using OpenAI. (github.com)

Gibt es auch als Extension: Explicare – Visual Studio Marketplace

Code Schnipsel: Service Provider

Dependency Injection macht das Leben einfacher auch in .NET MAUI. Hin und wieder ist es notwendig ein Service zu referenzieren das nicht über den Konstruktor kommt. Hier kommt ein Code Schnipsel für einen Service Provider:

public static class ServiceProvider
{
    public static TService GetService<TService>()
        => Current.GetService<TService>();

    public static IServiceProvider Current
        =>
#if WINDOWS10_0_17763_0_OR_GREATER
			MauiWinUIApplication.Current.Services;
#elif ANDROID
            MauiApplication.Current.Services;
#elif IOS || MACCATALYST
			MauiUIApplicationDelegate.Current.Services;
#else
			null;
#endif
}

Erläuterung:

Methode GetService():

Diese Methode ist eine Abkürzung, um einen Dienst vom Typ TService zu erhalten.
Sie delegiert den Aufruf an die Methode GetService() des aktuellen IServiceProviders.
Eigenschaft Current: Diese Eigenschaft gibt den aktuellen IServiceProvider auf der Basis der Plattform zurück.
Sie verwendet Präprozessor-Direktiven (#if, #elif, #else, #endif) zur bedingten Kompilierung unterschiedlichen Codes auf der Grundlage der Plattform.
Die plattformspezifische Eigenschaft Current wird auf der Grundlage der Kompilierungskonstanten ausgewählt:
Für Windows (UWP) mit Version 17763.0 oder höher wird MauiWinUIApplication.Current.Services verwendet.
Für Android wird MauiApplication.Current.Services verwendet.
Für iOS und Mac Catalyst verwendet es MauiUIApplicationDelegate.Current.Services.
Für andere Plattformen wird die Eigenschaft als Fallback auf null gesetzt.
Diese ServiceProvider-Klasse eine einfache und konsistente Möglichkeit bietet, Dienste in einer plattformübergreifenden MAUI-Anwendung abzurufen, wobei plattformspezifische Details, der Einfachheit halber, weggelassen werden. Das Code Schnipsel Service Provider verwendet die bedingte Kompilierung, um die Unterschiede bei der Abfrage von Diensten auf der Grundlage des zugrunde liegenden Betriebssystems zu behandeln.

Alle CodeSchnipsel für MAUI