其实我试着设计某种电子商店。 我感兴趣的是从管理面板(在运行时)创建多种产品。
例如,我有基本的产品类
public class Product
{
public double Price {get;set;}
}
我想制作一些有ScreenDiagonal
的电视课程public class TV : Product
{
public int ScreenDiagonal {get;set;}
}
但是我需要在运行时创建这样的类,并为它设置属性。 这样做的最佳做法是什么?反思或其他一些想法?
答案 0 :(得分:1)
使用CodeDom,如下所示:
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));
}
}
它使用此类创建一个程序集“Test.Dynamic.dll”
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;
}
}
}
}
您还可以使用C#的动态功能
DynamicEntity类,无需在运行时创建任何内容
public class DynamicEntity : DynamicObject
{
private IDictionary<string, object> _values;
public DynamicEntity(IDictionary<string, object> values)
{
_values = values;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
if (_values.ContainsKey(binder.Name))
{
result = _values[binder.Name];
return true;
}
result = null;
return false;
}
}
并像这样使用
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;