Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use custom class with dynamic compilation

I have a form that i dynamicly compiled and i have a style class. When i copy this style class to my form source and compile it all works fine. But how can i use this style class without copy it to my form source. My main program that compile this form has this class, how can i use it? Maybe i can pass style class to this for with i compile it, like a var?

Program source:

using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Windows.Forms;
using Microsoft.CSharp;

namespace dynamic
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            new Thread(newForm).Start();
        }

        public void newForm()
        {
            using (CSharpCodeProvider provider = new CSharpCodeProvider(new Dictionary<string, string>
                {
                    {"CompilerVersion", "v4.0"}
                }))
            {

                var parameters = new CompilerParameters
                {
                    GenerateExecutable = false, // Create a dll
                    GenerateInMemory = true, // Create it in memory
                    WarningLevel = 3, // Default warning level
                    CompilerOptions = "/optimize", // Optimize code
                    TreatWarningsAsErrors = false // Better be false to avoid break in warnings
                };

                parameters.ReferencedAssemblies.Add("mscorlib.dll");
                parameters.ReferencedAssemblies.Add("System.dll");
                parameters.ReferencedAssemblies.Add("System.Core.dll");
                parameters.ReferencedAssemblies.Add("System.Data.dll");
                parameters.ReferencedAssemblies.Add("System.Drawing.dll");
                parameters.ReferencedAssemblies.Add("System.Xml.dll");
                parameters.ReferencedAssemblies.Add("System.Windows.Forms.dll");

                var source = File.ReadAllText("form.txt");
                CompilerResults results = provider.CompileAssemblyFromSource(parameters, source);
                Type type = results.CompiledAssembly.GetType("myForm.Form1");
                object compiledObject = Activator.CreateInstance(type);

                type.GetMethod("ShowDialog", new Type[0]).Invoke(compiledObject, new object[] {});

                MessageBox.Show("formClosed");
            }
        }
    }
}

Style folder: enter image description here

Form source:

using System;
using System.Windows.Forms;

namespace myForm
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            var newTmr = new Timer { Interval = 1000 };
            newTmr.Tick += count;
            newTmr.Enabled = true;
        }

        private void count(Object myObject, EventArgs myEventArgs)
        {
            timer.Value2 = (Int32.Parse(timer.Value2) + 1).ToString();
        }

        private void button1_Click(object sender, System.EventArgs e)
        {
            MessageBox.Show("clicked");
        }

        private void nsButton1_Click(object sender, EventArgs e)
        {
            MessageBox.Show("button");
        }
    }
}
namespace myForm
{
    partial class Form1
    {
        /// <summary>
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Windows Form Designer generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            this.nsTheme1 = new myForm.NSTheme();
            this.nsButton1 = new myForm.NSButton();
            this.timer = new myForm.NSLabel();
            this.nsControlButton1 = new myForm.NSControlButton();
            this.nsTheme1.SuspendLayout();
            this.SuspendLayout();
            // 
            // nsTheme1
            // 
            this.nsTheme1.AccentOffset = 0;
            this.nsTheme1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(50)))), ((int)(((byte)(50)))), ((int)(((byte)(50)))));
            this.nsTheme1.BorderStyle = System.Windows.Forms.FormBorderStyle.None;
            this.nsTheme1.Colors = new myForm.Bloom[0];
            this.nsTheme1.Controls.Add(this.nsControlButton1);
            this.nsTheme1.Controls.Add(this.timer);
            this.nsTheme1.Controls.Add(this.nsButton1);
            this.nsTheme1.Customization = "";
            this.nsTheme1.Dock = System.Windows.Forms.DockStyle.Fill;
            this.nsTheme1.Font = new System.Drawing.Font("Verdana", 8F);
            this.nsTheme1.Image = null;
            this.nsTheme1.Location = new System.Drawing.Point(0, 0);
            this.nsTheme1.Movable = true;
            this.nsTheme1.Name = "nsTheme1";
            this.nsTheme1.NoRounding = false;
            this.nsTheme1.Sizable = true;
            this.nsTheme1.Size = new System.Drawing.Size(284, 274);
            this.nsTheme1.SmartBounds = true;
            this.nsTheme1.StartPosition = System.Windows.Forms.FormStartPosition.WindowsDefaultLocation;
            this.nsTheme1.TabIndex = 0;
            this.nsTheme1.Text = "nsTheme1";
            this.nsTheme1.TransparencyKey = System.Drawing.Color.Empty;
            this.nsTheme1.Transparent = false;
            // 
            // nsButton1
            // 
            this.nsButton1.Location = new System.Drawing.Point(100, 166);
            this.nsButton1.Name = "nsButton1";
            this.nsButton1.Size = new System.Drawing.Size(75, 23);
            this.nsButton1.TabIndex = 0;
            this.nsButton1.Text = "nsButton1";
            this.nsButton1.Click += new System.EventHandler(this.nsButton1_Click);
            // 
            // timer
            // 
            this.timer.Font = new System.Drawing.Font("Segoe UI", 11.25F, System.Drawing.FontStyle.Bold);
            this.timer.Location = new System.Drawing.Point(91, 82);
            this.timer.Name = "timer";
            this.timer.Size = new System.Drawing.Size(101, 23);
            this.timer.TabIndex = 1;
            this.timer.Text = "nsLabel1";
            this.timer.Value1 = "Timer: ";
            this.timer.Value2 = "0";
            // 
            // nsControlButton1
            // 
            this.nsControlButton1.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
            this.nsControlButton1.ControlButton = myForm.NSControlButton.Button.Close;
            this.nsControlButton1.Location = new System.Drawing.Point(262, 4);
            this.nsControlButton1.Margin = new System.Windows.Forms.Padding(0);
            this.nsControlButton1.MaximumSize = new System.Drawing.Size(18, 20);
            this.nsControlButton1.MinimumSize = new System.Drawing.Size(18, 20);
            this.nsControlButton1.Name = "nsControlButton1";
            this.nsControlButton1.Size = new System.Drawing.Size(18, 20);
            this.nsControlButton1.TabIndex = 2;
            this.nsControlButton1.Text = "nsControlButton1";
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(284, 274);
            this.Controls.Add(this.nsTheme1);
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
            this.Name = "Form1";
            this.Text = "Form1";
            this.nsTheme1.ResumeLayout(false);
            this.ResumeLayout(false);

        }

        #endregion

        private NSTheme nsTheme1;
        private NSButton nsButton1;
        private NSControlButton nsControlButton1;
        private NSLabel timer;
    }
}

Style source: http://pastebin.com/CjmQQ9ND

Project source - https://yadi.sk/d/ChtMacrsraD4g If you compile this source, all will work fine. That because i use style at form.txt file. I separated form from style at form.txt file. I have this style at my main program (you can see that at screenshot). How can i send this style class to my dynamicly compiled form, so form can use it.

like image 465
SLI Avatar asked May 07 '16 09:05

SLI


3 Answers

You should be able to simply append the style to the source like so:

var source = File.ReadAllText("form.txt");

source += Environment.NewLine;
source += File.ReadAllText("style.txt");
like image 183
Artail Avatar answered Nov 07 '22 22:11

Artail


Inside Form.txt file instead of the classes in order prescribes the macro:

namespace myForm
{
<%THEME%>
}

namespace myForm
{
<%THEMEBASE%>
}

Before compile, load style files and replace them in the code form:

//Load style files
var NSThemeSource = File.ReadAllText(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"..\..\Class\Style\NSTheme.cs"));
var themeBaseSource = File.ReadAllText(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"..\..\Class\Style\ThemeBase154.cs"));
var source = File.ReadAllText(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Form.txt"));

//Substitute in the form styles
source = source.Replace("<%THEME%>", NSThemeSource);
source = source.Replace("<%THEMEBASE%>", themeBaseSource);

P.S. You can switch build action for style files at Embedded Resource so you can get style class from exe. And use this helper - http://www.vcskicks.com/embedded-resource.php

Than you need to change code to:

var NSThemeSource = ResourceHelper.GetEmbeddedResource("Class/Style/NSTheme.cs");
var themeBaseSource = ResourceHelper.GetEmbeddedResource("Class/Style/ThemeBase154.cs");
like image 28
SLI Avatar answered Nov 07 '22 22:11

SLI


First, you need to make classes, enums, and etc. public in NSTheme.cs and ThemeBase154.cs. (it is better to put into some namespace, rather than having them in the global (dynamic) namespace).

Then, add parameters.ReferencedAssemblies.Add("dynamic.exe"); to you exe file (you might want to put your styles in a separate dll).

After it, in your form.txt add using dynamic; and remove qualifiers from new myForm.NSTheme() (so, it becomes new NSTheme()).

Now you can use your styles without coping them to your form class.

In case you miss something, check the CompilerResults results errors for particular problems.

like image 28
Sergey L Avatar answered Nov 07 '22 22:11

Sergey L