2012-12-01 66 views
1

其实我试图设计某种电子商店。 我有兴趣从管理面板(运行时)创建多种产品。.NET动态类属性

比如我有基本的产品类

public class Product 
{ 
    public double Price {get;set;} 
} 

我想创建具有ScreenDiagonal

public class TV : Product 
{ 
    public int ScreenDiagonal {get;set;} 
} 

一些电视类,但我需要建立这样的类在运行时,并设置属性它。 这样做的最佳做法是什么?反思或其他想法?

回答

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)); 
     } 
    } 

它在它

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#

动态特性与此类创建一个程序集 'Test.Dynamic.dll'

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;