0

I'm using RazorEngine for Razor Template parsing and trying to make use of its Roslyn code.

I know my issue is that I'm using a base-type (ViewBase<t>) in my razor views, and it's not being constructed (As it has a ctor parameter).

However after much googling, I can't find a way to tell Emit() how to make an instance of my type.

Below is the code it uses - the source code generates fine, and an omitted version is included below.

Is there some sort of factory of some sort I can provide in which it can use to generate this type?

When I call emit I get the error There is no argument given that corresponds to the required formal parameter 'componentContext' of 'ViewBase<MyModelType>.ViewBase(IComponentContext)' - So how would I tell emit() how to create a instance of my type ViewBase<T>

Creating an empty CTOR works fine - but isn't what I require.

public override Tuple<Type, CompilationData> CompileType(TypeContext context)
        {
            var sourceCode = GetCodeCompileUnit(context);
            var assemblyName = GetAssemblyName(context);

            (new PermissionSet(PermissionState.Unrestricted)).Assert();
            var tempDir = GetTemporaryDirectory();

            var sourceCodeFile = Path.Combine(tempDir, String.Format("{0}.{1}", assemblyName, SourceFileExtension));
            File.WriteAllText(sourceCodeFile, sourceCode);

            var references = GetAllReferences(context);

            var compilation =
                GetEmptyCompilation(assemblyName)
                    .AddSyntaxTrees(
                        GetSyntaxTree(sourceCode, sourceCodeFile))
                    .AddReferences(GetMetadataReferences(references));

            compilation =
                compilation
                    .WithOptions(
                        CreateOptions(context)
                            .WithOutputKind(OutputKind.DynamicallyLinkedLibrary)
                            .WithPlatform(Platform.AnyCpu)
                            .WithSourceReferenceResolver(new RazorEngineSourceReferenceResolver(sourceCodeFile)));

            var assemblyFile = Path.Combine(tempDir, String.Format("{0}.dll", assemblyName));

            var assemblyPdbFile = Path.Combine(tempDir, String.Format("{0}.pdb", assemblyName));
            var compilationData = new CompilationData(sourceCode, tempDir);

            using (var assemblyStream = File.Open(assemblyFile, FileMode.Create, FileAccess.ReadWrite))
            using (var pdbStream = File.Open(assemblyPdbFile, FileMode.Create, FileAccess.ReadWrite))
            {
                var opts = new EmitOptions()
                    .WithPdbFilePath(assemblyPdbFile);
                var pdbStreamHelper = pdbStream;

                if (IsMono())
                {
                    opts = opts.WithDebugInformationFormat(DebugInformationFormat.PortablePdb);
                }

                var result = compilation.Emit(assemblyStream, pdbStreamHelper, options: opts);

            }
        }

My generated view code

namespace CompiledRazorTemplates.Dynamic
{

#line default
#line hidden
    ;
    using System;
    //my load of other using statements...

    public class RazorEngine_99d043dd3e3d4c3ca787d42dd7a0bb6b : ViewBase<MyModelType>
    {
        #line hidden
        public RazorEngine_99d043dd3e3d4c3ca787d42dd7a0bb6b()
        {
        }

        #pragma warning disable 1998
        public override async Task Execute()
        {
..... OMITTED
        }
    }
}


public ViewBase(IComponentContext componentContext)
{
    Contract.Requires(componentContext != null);

    _componentContext = componentContext;
}
Stuart.Sklinar
  • 3,683
  • 4
  • 35
  • 89
  • 1
    Your question is unclear. Are you asking how to make the Razor compiler generate a ctor that calls your base class ctor with a parameter? – SLaks Mar 13 '18 at 16:48
  • Sorry - yes, when I call `emit` I get the error `There is no argument given that corresponds to the required formal parameter 'componentContext' of 'ViewBase.ViewBase(IComponentContext)'` - So how would I tell `emit()` how to create a instance of my type `ViewBase` Creating an empty CTOR works fine - but isn't what I require. – Stuart.Sklinar Mar 13 '18 at 16:54

1 Answers1

2

You're asking about the Razor compiler, not about Roslyn compilation.

I don't think there is any way to do that.

However, you could use a Roslyn CSharpSyntaxRewriter to find the existing constructor in your SyntaxTree and rewrite it to have & pass a parameter.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964