【问题标题】:.NET dynamic class properties.NET 动态类属性
【发布时间】:2012-12-02 02:57:17
【问题描述】:

实际上,我尝试设计某种电子商店。 我对从管理面板(运行时)创建多种产品感兴趣。

例如我有基本的产品类

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

我想创建一些具有 ScreenDiagonal 的电视类

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

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

【问题讨论】:

    标签: .net asp.net-mvc reflection


    【解决方案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;
    

    【讨论】:

      猜你喜欢
      • 2015-08-15
      • 1970-01-01
      • 2020-01-08
      • 2021-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多