Wolfram Language for Application Development:

How to Take Full Advantage of NETLink`

Andrew Yule, Assured Flow Solutions

Join the Conversation #WolframTechConf

Outline

Background / motivation

Introduction to .NET

Part 1: Calling Wolfram Language from .NET

Introduction to NETLink`

Part 2: Calling .NET from Wolfram Language

Background

About me

Chemical engineer in the oil and gas industry

Using Mathematica and the Wolfram Language for over 6 years

Assured Flow Solutions

Specialty engineering/consulting that focuses on solving production related issues for oil and gas companies

Use a combination of simulation modeling and production chemistry testing to identify issues and develop strategies to avoid them

ImageCrop[Import["\\\\Mac\\iCloud\\AFS\\Conferences\\Wolfram Technical Conferences\\2017\\Presentation Images\\Company_Overview_Small.png"],{700,435},Top]

Flow assurance?

Within the industry, our specialty is called Flow Assurance as we attempt to assure flow of hydrocarbons from reservoir to topsides

Flow assurance is necessary for many reasons the biggest of which are safety and profitability

Majority of work falls within either engineering category or production chemistry category

ImageCollage[{
Import["\\\\Mac\\iCloud\\AFS\\Conferences\\Wolfram Technical Conferences\\2017\\Presentation Images\\Oil Platform_Small.png"],
Import["\\\\Mac\\iCloud\\AFS\\Conferences\\Wolfram Technical Conferences\\2017\\Presentation Images\\FieldLayout.jpg"],
Import["\\\\Mac\\iCloud\\AFS\\Conferences\\Wolfram Technical Conferences\\2017\\Presentation Images\\JTCooling.png"],
Import["\\\\Mac\\iCloud\\AFS\\Conferences\\Wolfram Technical Conferences\\2017\\Presentation Images\\Rocking Cell_Small.png"],
Import["\\\\Mac\\iCloud\\AFS\\Conferences\\Wolfram Technical Conferences\\2017\\Presentation Images\\Wax_Small.png"],
Import["\\\\Mac\\iCloud\\AFS\\Conferences\\Wolfram Technical Conferences\\2017\\Presentation Images\\Asphaltene_Small.png"]
},ImagePadding->15,Background->White,Method->"Rows",ImageSize->800]

Background

Assured Flow Solutions’ Alex

Named after the library of Alexandria - one of the largest and most significant libraries of the ancient world

Show[Import["\\\\Mac\\iCloud\\AFS\\Conferences\\Wolfram Technical Conferences\\2017\\Presentation Images\\Alex_Library_Small.png"],ImageSize->500]

An attempt to capture our knowledge in a consistent and maintainable way

Currently contains 41 unique utilities

Developed in Mathematica and distributed via Enterprise CDF

Utilities are combinations of calculations and workflows

Leverage power of enterprise CDF by allowing for arbitrary InputFields and importing of any file type

SlideView[Grid[{#}]&/@ArrayReshape[Show[Import[#],ImageSize->500]&/@SortBy[FileNames[__~~".png","\\\\Mac\\iCloud\\AFS\\Conferences\\Wolfram Technical Conferences\\2017\\Alex Screenshots"],FileBaseName[#]&],{6,2}]]

Needed something more

As we expanded the reach of Alex, we realized there were a number of areas where we the ability to interface better with some of our 3rd party software

Created an initiative to investigate NETLink and what capabilities it had

Introduction to .NET

What is .NET?

.NET is the foundation for most of Windows and the majority of programs that run on Windows

Key feature is that many languages can be compiled into the .NET Common Language Runtime and executed (C#, VB, C++ etc.)

Quickly expanding reach into other platforms (mono / xamarian)

Import["\\\\Mac\\iCloud\\AFS\\Conferences\\Wolfram Technical Conferences\\2017\\Presentation Images\\NETImage.png"]

Why do we need .NET?

Access to forms and other windows controls

Access to third party DLLs

Access to other windows technologies (Excel)

Part 1: Calling Wolfram Language from .NET

Example

Creating a Mathematica Kernel Link

SystemOpen["\\\\Mac\\iCloud\\AFS\\Source Code\\WolframTechConference2017\\WolframLanguageFromNET\\WolframLanguageFromNET\\bin\\Debug\\WolframLanguageFromNET.exe"];

Import["\\\\Mac\\iCloud\\AFS\\Conferences\\Wolfram Technical Conferences\\2017\\Presentation Images\\Creating a new KernelLink.png"]

Things to keep in mind

Useful for when you have a .NET application but need to be able to do some calculations with the Wolfram Language

A few dll’s must be present in your applications directory - Wolfram.NETLink.dll, ml32i4.dll (32 bit), ml64i4.dll (64 bit)

Introduction to NETLink`

NETLink`

Technology integrated into the Mathematica that allows for direct communication with .NET

Requires the .NET framework to be installed (or some equivalent like mono)

Gives working with .NET objects the Wolfram touch

Lets you work in a truly interpreted environment

Basic syntax

Needs["NETLink`"];

InstallNET[];

Creating new objects

Import["\\\\Mac\\iCloud\\AFS\\Conferences\\Wolfram Technical Conferences\\2017\\Presentation Images\\PersonClass.png"]

personClass=NETNew[{"NETFromWolframLanguage.Person","\\\\Mac\\iCloud\\AFS\\Source Code\\WolframTechConference2017\\NETFromWolframLanguage\\NETFromWolframLanguage\\bin\\Debug\\NETFromWolframLanguage.dll"},"John","Doe"]

Accessing properties and calling methods

personClass@FirstName 
personClass[LastName]

Part 2: Calling .NET from Wolfram Language

Example: Using an existing code base to perform some computation

Import["\\\\Mac\\iCloud\\AFS\\Conferences\\Wolfram Technical Conferences\\2017\\Presentation Images\\PerformAddition.png"]

calculationClass=NETNew[{"NETFromWolframLanguage.Calculations","\\\\Mac\\iCloud\\AFS\\Source Code\\WolframTechConference2017\\NETFromWolframLanguage\\NETFromWolframLanguage\\bin\\Debug\\NETFromWolframLanguage.dll"}]

calculationClass@PerformAddition[2,2]

Example: Using an existing Kernel Link

Show[Import["\\\\Mac\\iCloud\\AFS\\Conferences\\Wolfram Technical Conferences\\2017\\Presentation Images\\ValueOfACalculation.png"],ImageSize->600]

a = "some text";

myClass=NETNew[{"NETFromWolframLanguage.Class1","\\\\Mac\\iCloud\\AFS\\Source Code\\WolframTechConference2017\\NETFromWolframLanguage\\NETFromWolframLanguage\\bin\\Debug\\NETFromWolframLanguage.dll"}];

myClass@WhatIsTheValueOfA[]

a=2+2;

myClass@WhatIsTheValueOfA[]

Part 2: Calling .NET from Wolfram Language

Creating Windows

Note: To access WPF controls you must first load the appropriate assemblies

LoadNETAssembly["C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\Framework\\.NETFramework\\v4.5\\PresentationFramework.dll"]

createWPFForm[]:=Module[{mForm},
mForm=NETNew["System.Windows.Window"];
mForm@Width=500;
mForm@Height=500;
mForm
];

wpfForm=createWPFForm[]

wpfForm@Show[];

Loading Special Assemblies

Accessing certain properties sometimes requires loading additional assemblies

LoadNETType["System.Windows.WindowStartupLocation"];

wpfForm=createWPFForm[]

wpfForm@WindowStartupLocation=System`Windows`WindowStartupLocation`CenterScreen;

wpfForm@Show[];

Working in a truly interpreted environment

Creating content for the window

createWindowContent[]:=Module[{mContent},
mContent=NETNew["System.Windows.Controls.DockPanel"];
mContent@LastChildFill=False;
mContent
];

wpfForm=createWPFForm[];
wpfContent=createWindowContent[];
wpfForm@Content=wpfContent;

wpfForm@Show[];

Change appearance

LoadNETType["System.Windows.Media.Brushes"];

wpfContent@Background=Brushes`LightGray;

Adding additional controls

Add a button

LoadNETType["System.Windows.VerticalAlignment"];
LoadNETType["System.Windows.HorizontalAlignment"];

createButton[]:=Module[{mButton},
mButton=NETNew["System.Windows.Controls.Button"];
mButton@Content="Some button";
mButton@VerticalAlignment=VerticalAlignment`Top;
mButton@HorizontalAlignment=HorizontalAlignment`Left;
mButton@Margin=NETNew["System.Windows.Thickness",10];
mButton
];

(*Create the button*)
wpfButton=createButton[];

(*Add the button to the WPF window*)
wpfContent@Children@Add[wpfButton];

Add a text box

createTextBlock[]:=Module[{mTxtBlk},
mTxtBlk=NETNew["System.Windows.Controls.TextBlock"];
mTxtBlk@VerticalAlignment=VerticalAlignment`Top;
mTxtBlk@HorizontalAlignment=HorizontalAlignment`Left;
mTxtBlk@Margin=NETNew["System.Windows.Thickness",10];
mTxtBlk@Text="Blank text block";
mTxtBlk
];

wpfTxtBlk=createTextBlock[];

wpfContent@Children@Add[wpfTxtBlk];

Assigning Functions

wpfFunc[arguments__]:=wpfTxtBlk@Text=DateString[];

AddEventHandler[wpfButton@Click,wpfFunc];

Efficiently combining .NET and Wolfram Language

At this point we have shown how you can create windows and controls all within the Wolfram Language

But, for large scale applications this may not be a feasible method

What if it were possible to use Wolfram Language for what it’s best at, while also using .NET for what it was best at, i.e. the best of both worlds?

MVVM

Model - View - View Model

Used in .NET programming to help efficently isolate business logic from user interface logic

Import["\\\\Mac\\iCloud\\AFS\\Conferences\\Wolfram Technical Conferences\\2017\\Presentation Images\\MVVM.png"]

Developing our own model

A note of caution - I am still figuring out the best practices for this myself

Show[Import["\\\\Mac\\iCloud\\AFS\\Conferences\\Wolfram Technical Conferences\\2017\\Presentation Images\\Xaml Screenshot.png"],ImageSize->700]

Show[Import["\\\\Mac\\iCloud\\AFS\\Conferences\\Wolfram Technical Conferences\\2017\\Presentation Images\\Button1Example.png"],ImageSize->500]

wpfForm=createWPFForm[];

wpfContent=NETNew[{"NETFromWolframLanguage2.ExampleWindow","\\\\Mac\\iCloud\\AFS\\Source Code\\WolframTechConference2017\\NETFromWolframLanguage2\\NETFromWolframLanguage2\\bin\\Debug\\NETFromWolframLanguage2.dll"}]

wpfForm@Content=wpfContent

wpfForm@Show[];

btnOneFunc[arguments__]:=Print[Now];

AddEventHandler[wpfContent@btnOne@Click,btnOneFunc]

What does this let us do?

Lets Wolfram Language do what it’s best it (computation)

Independently control the UI

wpfForm=createWPFForm[];

wpfContent=NETNew[{"NETFromWolframLanguage2.ExampleWindow","\\\\Mac\\iCloud\\AFS\\Source Code\\WolframTechConference2017\\NETFromWolframLanguage2\\NETFromWolframLanguage2\\bin\\Debug\\NETFromWolframLanguage2.dll"}]

wpfForm@Content=wpfContent

btnOneFunc[arguments__]:=Module[{},
wpfContent@status@Text="Calculating...";
Pause[5];
wpfContent@txtOne@Text=ToString[N[2+2]];
wpfContent@status@Text="Ready";
];

AddEventHandler[wpfContent@btnOne@Click,btnOneFunc]

wpfForm@ShowDialog[];

Even let Wolfram Language perform logic for the UI

wpfForm=createWPFForm[];

wpfContent=NETNew[{"NETFromWolframLanguage2.ExampleWindow","\\\\Mac\\iCloud\\AFS\\Source Code\\WolframTechConference2017\\NETFromWolframLanguage2\\NETFromWolframLanguage2\\bin\\Debug\\NETFromWolframLanguage2.dll"}]

wpfForm@Content=wpfContent

filterText[arguments__]:=Module[{mInputText,mAvailableNames,mFilteredNames},
wpfContent@lstViewOne@Items@Clear[];
mInputText=wpfContent@txtBoxOne@Text;
mAvailableNames=wpfContent@names;
If[mInputText=="",Table[wpfContent@lstViewOne@Items@Add[name],{name,mAvailableNames}];Return[];];
mFilteredNames=Cases[mAvailableNames,x_/;StringContainsQ[x,mInputText,IgnoreCase->True]];
Table[wpfContent@lstViewOne@Items@Add[name],{name,mFilteredNames}];
];

AddEventHandler[wpfContent@txtBoxOne@TextChanged,filterText]

wpfForm@ShowDialog[];

Extra Items

Show vs. ShowDialog

Calling ShowDialog[] on a window makes the Wolfram kernel dedicated to .NET

This allows other functionality like UI updating to occur in addition to backend calculations

Similar effect as DoNETModal[] and DoNETModeless[]

Debugging

Debugging can be performed by launching or attaching to InstallableNET.exe

Grid[{{Show[Import["\\\\Mac\\iCloud\\AFS\\Conferences\\Wolfram Technical Conferences\\2017\\Presentation Images\\AttachToInstallableNET.png"],ImageSize->600],Style["→",30,Bold],Show[Import["\\\\Mac\\iCloud\\AFS\\Conferences\\Wolfram Technical Conferences\\2017\\Presentation Images\\DebugFromWL.png"],ImageSize->600]}}]

Conclusions

Like all of Wolfram’s technology, NETLink` is a powerful tool and we are only scratching the surface here

For simple applications needing advanced calculations, consider calling the Wolfram Language directly from .NET

For advanced .NET development consider prototyping or even fully developing your application from the Wolfram Language

Experiment with NETLink`! More is possible than you might imagine!