रनटाइम पर आने वाले प्रकारों से गतिशील रूप से एक वर्ग बनाना


20

क्या सी # में (या किसी अन्य भाषा में) निम्नलिखित करना संभव है?

  1. मैं एक डेटाबेस से डेटा ला रहा हूं। रन टाइम में मैं प्राप्त किए गए कॉलम के कॉलम और डेटा प्रकारों की संख्या की गणना कर सकता हूं।

  2. आगे मैं इन डेटा प्रकारों के साथ फ़ील्ड के रूप में एक "वर्ग" बनाना चाहता हूं। मैं उन सभी अभिलेखों को संग्रहीत करना चाहता हूं जो मैंने एक संग्रह में प्राप्त किए थे।

समस्या यह है कि मैं चरण 1 और 2 दोनों रनटाइम पर करना चाहता हूं

क्या यह संभव है? मैं वर्तमान में C # का उपयोग कर रहा हूं, लेकिन यदि मुझे आवश्यकता है तो मैं कुछ और पर स्थानांतरित कर सकता हूं।


4
क्या आपको वास्तव में इसकी आवश्यकता है? आप निश्चित रूप से (ए) एक कस्टम वर्ग उत्पन्न कर सकते हैं जैसा कि दूसरों ने बताया है, लेकिन आपको (बी) को यह भी जानना होगा कि इसे रन टाइम पर कैसे उपयोग किया जाए। भाग (बी) मुझे बहुत काम की तरह लगता है। डेटासेट ऑब्जेक्ट या किसी प्रकार के संग्रह जैसे शब्दकोश के अंदर डेटा रखने में क्या गलत है? तुम क्या करने की कोशिश कर रहे हो?
जॉब

सुनिश्चित करें कि आपके पास रोब कॉनरी dynamicद्वारा बड़े पैमाने पर किए गए काम पर एक नज़र है : blog.wekeroad.com/helpy-stuff/and-i-shall-call-it-massive
रॉबर्ट हार्वे

1
पायथन गतिशील वर्ग घोषणा के लिए अनुमति देता है, और वास्तव में यह आम है। 2001 के आसपास से डेविड मर्टज़ द्वारा एक ट्यूटोरियल था (मैंने इसके लिए खोज की लेकिन सटीक लिंक नहीं मिल सका)। यह सीधा है।
smci

@RobertHarvey आपके द्वारा साझा किया गया लिंक मृत है। क्या आप जानते हैं कि मुझे यह कहां मिल सकता है?
जोज

1
यद्यपि तकनीकी रूप से संभव है, मुझे ऐसा करने के मूल्य पर सवाल उठाना होगा। मजबूत टाइपिंग और कक्षाओं की बात यह है कि संकलित समय पर आप वाक्यविन्यास त्रुटियों की जांच करने के लिए कक्षा की जानकारी का उपयोग करने में सक्षम हैं (गतिशील JITers की नई पीढ़ी इसके बिना अनुकूलन कर सकती है)। स्पष्ट रूप से टाइप किए गए वातावरण में गतिशील टाइपिंग का उपयोग करने की कोशिश करने का मतलब यह होगा कि आप या तो प्रतिमान के सभी फायदे खो देंगे ...
ArTs

जवाबों:


28

कोडडोम का उपयोग करें। यहाँ कुछ शुरू करने के लिए है

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 # की गतिशील सुविधाओं का भी उपयोग कर सकते हैं

डायनेमिकइंटरिटी क्लास, रनटाइम पर कुछ भी बनाने की आवश्यकता नहीं है

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

और इसे इस तरह से उपयोग करें

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;

6

हां, आप ऐसा करने के लिए प्रतिबिंब उत्सर्जन का उपयोग कर सकते हैं । मैनिंग के पास इस पर आने वाली एक उत्कृष्ट पुस्तक है: .NET में Metaprogramming

BTW: क्यों न केवल शब्दकोशों के साथ एक सूची का उपयोग करें या प्रत्येक रिकॉर्ड को कुंजी के रूप में फ़ील्ड नामों के साथ संग्रहीत करें?


1
मेटा-प्रोग्रामिंग संदर्भों के लिए धन्यवाद। यहाँ कुछ अन्य मैंने पाया है: vslive.com/Blogs/News-and-Tips/2016/03//-
लियो गुरडियन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.