Use CodeDom. Aqui está algo para começar
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.CSharp;
using System.CodeDom.Compiler;
using System.CodeDom;
namespace Test
{
class Program
{
static void Main(string[] args)
{
string className = "BlogPost";
var props = new Dictionary<string, Type>() {
{ "Title", typeof(string) },
{ "Text", typeof(string) },
{ "Tags", typeof(string[]) }
};
createType(className, props);
}
static void createType(string name, IDictionary<string, Type> props)
{
var csc = new CSharpCodeProvider(new Dictionary<string, string>() { { "CompilerVersion", "v4.0" } });
var parameters = new CompilerParameters(new[] { "mscorlib.dll", "System.Core.dll"}, "Test.Dynamic.dll", false);
parameters.GenerateExecutable = false;
var compileUnit = new CodeCompileUnit();
var ns = new CodeNamespace("Test.Dynamic");
compileUnit.Namespaces.Add(ns);
ns.Imports.Add(new CodeNamespaceImport("System"));
var classType = new CodeTypeDeclaration(name);
classType.Attributes = MemberAttributes.Public;
ns.Types.Add(classType);
foreach (var prop in props)
{
var fieldName = "_" + prop.Key;
var field = new CodeMemberField(prop.Value, fieldName);
classType.Members.Add(field);
var property = new CodeMemberProperty();
property.Attributes = MemberAttributes.Public | MemberAttributes.Final;
property.Type = new CodeTypeReference(prop.Value);
property.Name = prop.Key;
property.GetStatements.Add(new CodeMethodReturnStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), fieldName)));
property.SetStatements.Add(new CodeAssignStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), fieldName), new CodePropertySetValueReferenceExpression()));
classType.Members.Add(property);
}
var results = csc.CompileAssemblyFromDom(parameters,compileUnit);
results.Errors.Cast<CompilerError>().ToList().ForEach(error => Console.WriteLine(error.ErrorText));
}
}
}
Ele cria um assembly 'Test.Dynamic.dll' com esta classe
namespace Test.Dynamic
{
public class BlogPost
{
private string _Title;
private string _Text;
private string[] _Tags;
public string Title
{
get
{
return this._Title;
}
set
{
this._Title = value;
}
}
public string Text
{
get
{
return this._Text;
}
set
{
this._Text = value;
}
}
public string[] Tags
{
get
{
return this._Tags;
}
set
{
this._Tags = value;
}
}
}
}
Você também pode usar os recursos dinâmicos do C #
Classe DynamicEntity, sem necessidade de criar nada em tempo de execução
public class DynamicEntity : DynamicObject
{
private IDictionary<string, object> _values;
public DynamicEntity(IDictionary<string, object> values)
{
_values = values;
}
public override IEnumerable<string> GetDynamicMemberNames()
{
return _values.Keys;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (_values.ContainsKey(binder.Name))
{
result = _values[binder.Name];
return true;
}
result = null;
return false;
}
}
E use assim
var values = new Dictionary<string, object>();
values.Add("Title", "Hello World!");
values.Add("Text", "My first post");
values.Add("Tags", new[] { "hello", "world" });
var post = new DynamicEntity(values);
dynamic dynPost = post;
var text = dynPost.Text;