VB My namespace code - for anyone who is interested

Add a reference to Microsoft.VisualBasic.dll, add the following code in a pas file to your project, and you have the VB My namespace:

namespace <your default namespace>;

interface 

uses
    Microsoft.VisualBasic.*;

type My = assembly static class
    private
        fApplication: MyApplication := MyProject.m_AppObjectProvider.GetInstance;
        fComputer: MyComputer := MyProject.m_ComputerObjectProvider.GetInstance;
        fSettings := PaysafeReconciliation.Properties.Settings.Default;
        fUser: Microsoft.VisualBasic.ApplicationServices.User := MyProject.m_UserObjectProvider.GetInstance;
     Assembly
        property Application: MyApplication read fApplication; 
        property Computer: Microsoft.VisualBasic.Devices.Computer read fComputer;
        property Settings: Properties.Settings read fSettings;
        property User: Microsoft.VisualBasic.ApplicationServices.User read fUser;
end;

type MyComputer = assembly class(Microsoft.VisualBasic.Devices.Computer);

type MyApplication = assembly class(Microsoft.VisualBasic.ApplicationServices.ApplicationBase);

type MyProject = assembly static class
    unit
        var m_ComputerObjectProvider := New MyProject.ThreadSafeObjectProvider<MyComputer>();
        var m_AppObjectProvider := New MyProject.ThreadSafeObjectProvider<MyApplication>();
        var m_UserObjectProvider := New MyProject.ThreadSafeObjectProvider<Microsoft.VisualBasic.ApplicationServices.User>();
end;

type ThreadSafeObjectProvider<T> nested in MyProject = unit class
private
    var m_Context:= New Microsoft.VisualBasic.MyServices.Internal.ContextValue<T>(); readonly;
assembly
    property GetInstance: T read if m_Context.Value = nil then Activator.CreateInstance<T>() else m_Context.Value;
public
end;

implementation

end.

Free to use for anyone that is interested - this code gives access to all computer resources (like the filesystem), the current user, the application settings and application properties.
The My.Webservices need generated code, so this one is not supported.

2 Likes

Ok if I create a reusable/shippable dll form this, and a GitHub repo?

Or actually, since this should be in the default namespace — what if I (optionally) make the build generate/inject this file intot the compile?

Done, for vNext, except for Settings. I’ll need exists() support n the compiler before I can do that, because not every project HAS a Settings class (yet).

For now, any project that references VB.dll will automatically get this:

namespace %rootnamespace%;

uses
  Microsoft.VisualBasic.*;

type
  My = assembly partial static class
  assembly
    property Application: MyApplication := MyProject.AppObjectProvider.GetInstance; readonly; lazy;
    property Computer: Microsoft.VisualBasic.Devices.Computer := MyProject.ComputerObjectProvider.GetInstance; readonly; lazy;
    //property Settings: Properties.Settings := %rootnamespace%.Properties.Settings.Default; readonly; lazy;
    property User: Microsoft.VisualBasic.ApplicationServices.User := MyProject.UserObjectProvider.GetInstance; readonly; lazy;
  end;

  MyComputer = assembly class(Microsoft.VisualBasic.Devices.Computer);

  MyApplication = assembly class(Microsoft.VisualBasic.ApplicationServices.ApplicationBase);

  MyProject = assembly static class
  unit
    property ComputerObjectProvider := new MyProject.ThreadSafeObjectProvider<MyComputer>(); readonly; lazy;
    property AppObjectProvider := new MyProject.ThreadSafeObjectProvider<MyApplication>(); readonly; lazy;
    property UserObjectProvider := new MyProject.ThreadSafeObjectProvider<Microsoft.VisualBasic.ApplicationServices.User>(); readonly; lazy;
  end;

  ThreadSafeObjectProvider<T> nested in MyProject = unit class
  private
    var fContext := new Microsoft.VisualBasic.MyServices.Internal.ContextValue<T>(); readonly;
  assembly
    property GetInstance: T read if fContext.Value = nil then Activator.CreateInstance<T>() else fContext.Value;
  end;

end.

(you can add Settings via second partial of there class, for now)

1 Like

Thanks Marc!

But the settings can be added:

namespace %rootnamespace%;
interface
uses
  Microsoft.VisualBasic.*;

type Properties.Settings = partial sealed class(System.Configuration.ApplicationSettingsBase);

type
  My = assembly partial static class
  unit
    method get_Settings: Properties.Settings;
  assembly
    property Application: MyApplication := MyProject.AppObjectProvider.GetInstance; readonly; lazy;
    property Computer: Microsoft.VisualBasic.Devices.Computer := MyProject.ComputerObjectProvider.GetInstance; readonly; lazy;
    property Settings: %rootnamespace%.Properties.Settings read get_Settings; lazy;
    property User: Microsoft.VisualBasic.ApplicationServices.User := MyProject.UserObjectProvider.GetInstance; readonly; lazy;
  end;

  MyComputer = assembly class(Microsoft.VisualBasic.Devices.Computer);

  MyApplication = assembly class(Microsoft.VisualBasic.ApplicationServices.ApplicationBase);

  MyProject = assembly static class
  unit
    property ComputerObjectProvider := new MyProject.ThreadSafeObjectProvider<MyComputer>(); readonly; lazy;
    property AppObjectProvider := new MyProject.ThreadSafeObjectProvider<MyApplication>(); readonly; lazy;
    property UserObjectProvider := new MyProject.ThreadSafeObjectProvider<Microsoft.VisualBasic.ApplicationServices.User>(); readonly; lazy;
  end;

  ThreadSafeObjectProvider<T> nested in MyProject = unit class
  private
    var fContext := new Microsoft.VisualBasic.MyServices.Internal.ContextValue<T>(); readonly;
  assembly
    property GetInstance: T read if fContext.Value = nil then Activator.CreateInstance<T>() else fContext.Value;
  end;
implementation
var _Settings: %rootnamespace%.Properties.Settings := nil;
method My.get_Settings: %rootnamespace%.Properties.Settings;
begin
  if _Settings = nil then
  begin
      var p: System.Reflection.PropertyInfo := (new %rootnamespace%.Properties.Settings).GetType.GetProperty("Default");
      if p = nil then
          _Settings := new Properties.Settings
      else
          _Settings := %rootnamespace%.Properties.Settings(p.GetValue(nil));
  end;
exit _Settings;
end;

end.

@ck: This code shows a problem with obfuscation; the reflected code works as long as the code it is not obfuscated

That makes sense of course, we need to think of a generic way to solve this, preferably without hardcoding the list of classes.

Found a small bug here. Properties & Settings should be fine in the next build.

1 Like

Hi Marc - for the settings fix, see above.
But a problem; it is compiled into the assembly, but you can not use it; there is no CC for My.

Theo: yes, but not every project HAS settings.

as for CC, yes right now the ide does t see the file yet, only the compiler does. but that doesn’t mean you can’t USE it? i’ll fix the IDE side later.

That’s what I fixed with that code.
The settings remains empty when there are no setings.

I can type it myself, but it means I have to type ESC after each word to prevent the CC to replace the words.
Without that, My.Computer.FileSystem becomes Microsoft.VisualBasic.MyGroupCollectionAttribute.Computer.FileSystem

Problem is that %rootnamespace%.Properties.Settings does not EXIST as a class, when there’s no settings. So the code will fail to compile.

Right, but Rome wasn’t built in a day :wink:

Thats why I added the line:
type Properties.Settings = partial sealed class(System.Configuration.ApplicationSettingsBase);

Try it - it works.

Ah, missed that part. Good idea!

that said, fixed it via

    {$IF EXISTS('%rootnamespace%.Properties.Settings')}
    property Settings: %rootnamespace%.Properties.Settings := %rootnamespace%.Properties.Settings.Default; readonly; lazy;
    {$ENDIF}

for vNext.

CC works for vNext, Fire and Water. This new logic does not just get used for the My.pas file, but also for any other source generated behind the scenes during build (eg R.java files on Android, and more).

1 Like

@mh, @ck, Can I have an internal build?

In 2313 with VS2017, the CC does not work.
If you type My. nothing happens. When you press Ctrl-Space to open the CC, the Oxygene output prints: Unknown identifier “My”

It does compile.

I don’t know what the status of this for VS is, iirc the issue is still open. I just fixed Fire/Water, as the VS IDE isn’t my area. it works there, and that’s what my previous post referred to ;).

Ok, misunderstood your statement.