Am really liking the new VB14 language features in VS2015 (like ?. notation and string interpolation). In our WinForms (.Net 4.5) application I use codedom compiler to run dynamic reporting code on the fly. Unfortunately this does not automatically support the new language features.
Imports System.CodeDom.Compiler
Namespace MAF.DB.BusinessObject.ReportService
Public Class VBReportCompiler
Implements IReportCompiler
Private ReadOnly ApplicationPath As String
''' <summary>
''' Create a report compiler with a reference to the location of the Wingman dlls. These need
''' to be referenced in the compilation, but the location differs between web and windows.
''' </summary>
''' <param name="ApplicationPath">Path to the binary folder</param>
Public Sub New(ApplicationPath As String)
Me.ApplicationPath = ApplicationPath
End Sub
Public Function Compile(convertedSourceCode As String, Optional ByRef reporter As IValidationReporter = Nothing,
Optional report As IBusinessObject = Nothing) As Object Implements IReportCompiler.Compile
If reporter Is Nothing Then reporter = IOC.Dependency.Resolve(Of IValidationReporter)()
Dim result As Object = Nothing
Try
If convertedSourceCode Is Nothing Then
reporter.Add(report, "Report definition missing or blank")
Else
Dim params As New CompilerParameters With {
.GenerateExecutable = False, ' Generate a DLL, not and EXE executable.
.GenerateInMemory = True, ' Generate the assembly in memory, don't save to a file
.IncludeDebugInformation = True
}
params.TempFiles.KeepFiles = False ' don't keep temporary source files.
' Add a reference to necessary strong-named assemblies.
With params.ReferencedAssemblies
.Add("Microsoft.VisualBasic.dll")
.Add("System.dll")
.Add("System.Core.dll")
.Add("System.Data.dll") 'Allows use in report of ADO data types
.Add("System.Data.DataSetExtensions.dll") 'Allows LINQ on DataTables
.Add("System.Drawing.dll") 'Allows access in report of GDI+ basic graphics functionality such as datatable
.Add("System.Xml.dll")
'Add References to required Wingman assemblies
.Add(IO.Path.Combine(ApplicationPath, "MAF.DB.dll")) 'Allows use in report of Data Access & Business Object functions and properties
.Add(IO.Path.Combine(ApplicationPath, "MAF.SharedClasses.dll"))
.Add(IO.Path.Combine(ApplicationPath, "DB.Foundation.dll"))
.Add(IO.Path.Combine(ApplicationPath, "MAF.Tracer.dll")) ' allows use in report of standard error messages
End With
' Create the VB compiler.
Dim provider = New VBCodeProvider() 'Use the current .Net Framework
Dim compRes = provider.CompileAssemblyFromSource(params, convertedSourceCode)
' Check whether we have any compile errors.
For Each compileError As CompilerError In compRes.Errors
reporter.Add(report, String.Format("Line {0}: {1}", compileError.Line, compileError.ErrorText))
Next
If reporter.Valid Then result = compRes.CompiledAssembly.CreateInstance("ReportCompiler")
End If
Catch ex As Exception
reporter.Add(report, "Unknown Error: " & ex.Message)
End Try
If Not reporter.Valid Then Return Nothing
Return result
End Function
End Class
In order to get it to work I've tried to add the Roslyn codedom nuget package but that generates two issues.
First problem is that it looks for the compiler in the wrong place \bin\debug\bin\roslyn\vbc.exe whereas the build process actually creates it in a folder \bin\debug\roslyn\ . Can anyone tell me how to resolve this as it fails my build server deployment?
Making a manual copy of the roslyn folder (work-around) and place it where codedom expects to find it is not a real solution but that raises the second issue that it expects an import of System.Web.HttpRequest and System.Web.HttpResponse. But am not compiling any web related code (winforms). So why is it expecting this?