Click here to Skip to main content
15,886,873 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have a WPF project that I need to compile, load as a DLL file, and access its components programmatically. I'm currently using the Roslyn Compiler in my function, but I'm open to alternative solutions if they can help resolve my issue. The problem I'm facing is that even though the compilation process completes successfully, I'm unable to access any of the Types defined in my WPF project from the compiled assembly.

What I have tried:

I've attempted to populate a Type array by loading the assembly and calling GetTypes(), but it returns an empty array. I have also ensured that the necessary assembly references are added using MetadataReference.CreateFromFile, including references to assemblies such as System.Windows and PresentationFramework. However, I'm still unable to access the Types defined in my project. I have tried various approaches such as MSBuild and CodeDom, but none of them have yielded the desired result. I would greatly appreciate any insights or suggestions on how to resolve this issue. Are there any additional steps or modifications I should consider in order to access the Types from the compiled WPF project?

I have also checked the emitResult.Diagnostics collection for any errors or warnings, but there are no reported issues during the compilation process. Here's a simplified version of the code I'm using in my function.


C#
public void CompileAndBuildWithRoslyn(string projectFilePath, string outputDirectory)
            {
                // Load the project
                var projectText = File.ReadAllText(projectFilePath);
                var projectId = ProjectId.CreateNewId();
                var versionStamp = VersionStamp.Create();
                var projectInfo = ProjectInfo.Create(projectId, versionStamp, "MyProject", "MyProject", LanguageNames.CSharp)
                    .WithFilePath(projectFilePath);
                var workspace = new AdhocWorkspace();
                var project = workspace.AddProject(projectInfo);

                // Get all documents from the project
                var documents = project.Documents.ToList();
                foreach (var document in documents)
                {
                    var text = File.ReadAllText(document.FilePath);
                    //var documentId = DocumentId.CreateNewId(project.Id);
                    var syntaxTree = CSharpSyntaxTree.ParseText(text);
                    var updatedDocument = document.WithSyntaxRoot(syntaxTree.GetRoot());
                    var updatedProject = project.AddDocument(updatedDocument.Name, syntaxTree.GetText());
                    project = updatedDocument.Project;
                }
                // Set compilation options
                var compilationOptions = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
                    .WithOptimizationLevel(OptimizationLevel.Debug);

                // Add references to the metadata references
                var metadataReferences = new List<MetadataReference>
                {
                    MetadataReference.CreateFromFile(typeof(object).Assembly.Location), // Add reference to the 'System' assembly
                    MetadataReference.CreateFromFile(typeof(System.Windows.MessageBox).Assembly.Location), // Add reference to the 'PresentationFramework' assembly (for System.Windows namespace)
                    
//I added reference to each single assembly used in my WPF project in this collection

                };

                // Create a compilation
                var compilation = CSharpCompilation.Create(
                    Path.GetFileNameWithoutExtension(projectFilePath),
                    documents.Select(doc => doc.GetSyntaxTreeAsync().Result),
                    metadataReferences,
                    compilationOptions
                );

                // Set the output file path
                var outputFile = Path.Combine(outputDirectory, $"{project.AssemblyName}.dll");

                // Perform the compilation
                EmitResult emitResult = compilation.Emit(outputFile);

                // Verify the compilation result
                if (emitResult.Success)
                {

                    // Load the compiled assembly
                    var assembly = Assembly.LoadFile(outputFile);

                    // Access components from the compiled assembly
                    var types = assembly.GetTypes(); // Get all types defined in the assembly

                    // Example: Instantiate and use a class from the compiled assembly
                    var myClassType = assembly.GetType("MPUserWPFApp.MVVM.ViewModels.Basics.BaseViewModel"); // Replace "Namespace.MyClass" with the correct namespace and class name
                    var myClassInstance = Activator.CreateInstance(myClassType);
                    var methodInfo = myClassType.GetMethod("Dispose"); // Replace "SomeMethod" with the correct method name
                    methodInfo.Invoke(myClassInstance, null); // Invoke the method on the instance

                    // Example: Access a static property from the compiled assembly
                    var myOtherClassType = assembly.GetType("Namespace.MyOtherClass"); // Replace "Namespace.MyOtherClass" with the correct namespace and class name
                    var staticProperty = myOtherClassType.GetProperty("SomeStaticProperty"); // Replace "SomeStaticProperty" with the correct property name
                    var propertyValue = staticProperty.GetValue(null); // Access the property value

                    // Example: Use a type defined in the compiled assembly
                    var customType = assembly.GetType("Namespace.CustomType"); // Replace "Namespace.CustomType" with the correct namespace and type name
                    var customInstance = Activator.CreateInstance(customType);
                    // ... Use the custom type instance as needed

                    // Note: Make sure to handle exceptions and perform proper error checking in your production code.

                    System.Windows.MessageBox.Show("Compilation and build process completed successfully.");
                }
                else
                {
                    System.Windows.MessageBox.Show("Compilation and build process failed.");
                    foreach (var diagnostic in emitResult.Diagnostics)
                    {
                        System.Diagnostics.Debug.WriteLine(diagnostic.ToString());
                    }
                }
            }

//I'm calling the function using this way :

        private void Compile_Click(object sender, RoutedEventArgs e)
        {
            string projectFilePath = @"C:\Users\iwass\source\repos\MPAPP\MPUSERAPP\MPUSERAPP.csproj";
            string OutPutDir = @"C:\Users\iwass\OneDrive\Bureau";
            CompileAndBuildWithRoslyn(projectFilePath, OutPutDir);
        }



Thank you in advance for your help!
Posted
Comments
[no name] 19-Jun-23 18:45pm    
Try accessing the dll "after" compiling, and not "during", and see if it makes a difference. Use the VS "object browser". Maybe the types are "private".
Wassa Bizo Ismaila 21-Jun-23 16:48pm    
Thank a lot ! I tried to compile access the .dll after compilation, but I still can see none of my types!

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900