ciao,
qualcuno sa come posso richiamare un assembly creato dinamicamente in memoria per passarlo come ReferencedAssemblies di CompilerParameters (senza scriverlo su file)?
mi spiego meglio :
usandolo così tutto funziona :codice:public static class Estensore<T> { public static T Estendi(object tipo, string nomeClasse, string nameSpace, Dictionary<string,string> proprieta) { CSharpCodeProvider CSharpCodeProvider = new CSharpCodeProvider(); ICodeCompiler Compilatore = CSharpCodeProvider.CreateCompiler(); CompilerParameters ParametriCompilatore = new CompilerParameters(); ParametriCompilatore.GenerateInMemory = true; ParametriCompilatore.IncludeDebugInformation = true; foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) { try { ParametriCompilatore.ReferencedAssemblies.Add(asm.Location); } catch { return default(T); } } StringBuilder CodiceSorgente = new StringBuilder(); CodiceSorgente.Append("using System;"); CodiceSorgente.Append("\n"); CodiceSorgente.Append("using System.Collections.Generic;"); CodiceSorgente.Append("\n"); CodiceSorgente.Append("using Test;"); CodiceSorgente.Append("\n"); CodiceSorgente.Append("using System.Text;"); CodiceSorgente.Append("\n"); CodiceSorgente.Append("using Microsoft.CSharp;"); CodiceSorgente.Append("\n"); CodiceSorgente.Append("using System.CodeDom.Compiler;"); CodiceSorgente.Append("\n"); CodiceSorgente.Append("namespace "); CodiceSorgente.Append(nameSpace); CodiceSorgente.Append("\n"); CodiceSorgente.Append("{\n"); CodiceSorgente.Append("public class "); CodiceSorgente.Append(nomeClasse); CodiceSorgente.Append(" : "); CodiceSorgente.Append(tipo.GetType().ToString()); CodiceSorgente.Append("\n"); CodiceSorgente.Append("{\n"); foreach(string nomeProprieta in proprieta.Keys) { string nomeProprietaMaiuscola = nomeProprieta.Substring(0,1).ToUpper() + nomeProprieta.Substring(1,nomeProprieta.Length-1); string minuscola = nomeProprieta.Substring(0,1).ToLower() + nomeProprieta.Substring(1,nomeProprieta.Length-1); CodiceSorgente.Append("public string "); CodiceSorgente.Append(nomeProprietaMaiuscola); CodiceSorgente.Append("{ get{ return " + minuscola + ";} set{ " + minuscola + " = value; }}"); CodiceSorgente.Append("\n"); CodiceSorgente.Append("\n"); CodiceSorgente.Append("string "); CodiceSorgente.Append(minuscola); CodiceSorgente.Append(" = "); CodiceSorgente.Append(@"""");CodiceSorgente.Append(proprieta[nomeProprieta]);CodiceSorgente.Append(@""""); CodiceSorgente.Append(";"); } CodiceSorgente.Append("public "); CodiceSorgente.Append(nomeClasse); CodiceSorgente.Append("() {"); CodiceSorgente.Append("\n}\n}\n}"); CompilerResults RisultatoCompilatore = Compilatore.CompileAssemblyFromSource(ParametriCompilatore, CodiceSorgente.ToString()); if (RisultatoCompilatore.Errors.HasErrors) { foreach (CompilerError Errore in RisultatoCompilatore.Errors) { if (!Errore.IsWarning) { return default(T); } } } Type t = null; for(int i = 0; i<RisultatoCompilatore.CompiledAssembly.GetTypes().Length;i++) { if(RisultatoCompilatore.CompiledAssembly.GetTypes()[i].Name==nomeClasse) { t = RisultatoCompilatore.CompiledAssembly.GetTypes()[i]; break; } } object o = t.InvokeMember(nomeClasse, System.Reflection.BindingFlags.CreateInstance, null, null, null); PropertyInfo[] properties = tipo.GetType().GetProperties//(); ( BindingFlags.CreateInstance //| BindingFlags.GetField | BindingFlags.GetProperty | BindingFlags.Instance //| BindingFlags.InvokeMethod //| BindingFlags.NonPublic | BindingFlags.Public //| BindingFlags.OptionalParamBinding ); foreach (PropertyInfo property in properties) { if (property.CanWrite) { object value = property.GetValue(tipo, null); property.SetValue(o, value, null); } } return (T)o; } }
ottengo ovviamente le proprietà della classe "SuperUser" più quelle ereditate da User.codice:using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Reflection; namespace Test { public partial class Form1 : Form { public Form1() { InitializeComponent(); User user = new User(); user.Password = "2312"; user.UserName ="paperino"; Dictionary<string, string> dizionario = new Dictionary<string, string>(); dizionario.Add("CodiceDiSicurezza", "123456"); user = Estensore<User>.Estendi(user, "SuperUser", "Test", dizionario); writeProperty(user); } void writeProperty(User user) { PropertyInfo[] properties = user.GetType().GetProperties//(); ( BindingFlags.CreateInstance //| BindingFlags.GetField | BindingFlags.GetProperty | BindingFlags.Instance //| BindingFlags.InvokeMethod //| BindingFlags.NonPublic | BindingFlags.Public //| BindingFlags.OptionalParamBinding ); this.dataGridView1.DataSource = properties; } } public class User { public string UserName { get; set; } public string Password { get; set; } } }
Il punto e che mi piacerebbe fare una cosa del genere :
in questo caso, la seconda volta che chiamo Estendi, eredito da "SuperUser" (non da User), in quanto il suo nuovo tipo è appunto "SuperUser".codice:User user = new User(); user.Password = "2312"; user.UserName ="paperino"; Dictionary<string, string> dizionario = new Dictionary<string, string>(); dizionario.Add("CodiceDiSicurezza", "123456"); user = Estensore<User>.Estendi(user, "SuperUser", "Test", dizionario); //writeProperty(user); dizionario.Clear(); dizionario.Add("CodiceDiSicurezza2", "123456"); user = Estensore<User>.Estendi(user, "Admin", "Test", dizionario); writeProperty(user);
ora il problema è che non voglio scrivere l'assembly su file, lo voglio tenere in memoria, quindi volevo sapere se esiste un modo per caricarlo nei parametri del compilatore senza passare location.
sicuramente è una ca***ta, ma ora ho un vuoto.codice:foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) { try { ParametriCompilatore.ReferencedAssemblies.Add(asm.????); } catch { return default(T); } }![]()
Grazie in anticipo per l'attenzione.![]()
![]()

Rispondi quotando