कैसे गतिशील रूप से एक वर्ग बनाने के लिए?


222

मेरे पास एक वर्ग है जो इस तरह दिखता है:

public class Field
{
    public string FieldName;
    public string FieldType;
}

और List<Field>मूल्यों के साथ एक वस्तु :

{"EmployeeID","int"},
{"EmployeeName","String"},
{"Designation","String"}

मैं एक ऐसी क्लास बनाना चाहता हूँ जो इस तरह दिखे:

Class DynamicClass
{
    int EmployeeID,
    String EmployeeName,
    String Designation
}

क्या इसे करने का कोई तरीका है?

मैं चाहता हूं कि यह रनटाइम पर उत्पन्न हो। मैं अपने फ़ाइल सिस्टम में एक भौतिक CS फ़ाइल नहीं चाहता हूँ।


4
क्या आप रनटाइम में उस क्लास का उपयोग करना चाहते हैं या केवल फाइल जेनरेट करना चाहते हैं?
डेमियन लेस्ज़्ज़स्की - वाश

मैं चाहता हूं कि यह रनटाइम में उत्पन्न हो। मैं अपने फाइल सिस्टम में एक भौतिक सीएस फ़ाइल नहीं चाहता। पहले उल्लेख नहीं करने के लिए क्षमा करें।
अश्वनाचार्य

16
आप हमें क्या आप करना चाहते हैं का मोटा अनुमान दे सकते हैं कर इस वर्ग के साथ?
जस्टिन

3
@Justin रनटाइम-हल किए गए इंटरफ़ेस को लागू करता है, उदाहरण के लिए।
एजेंटफेयर

कोई इसे खिला सकता हैSystem.ServiceModel.ChannelFactory<MyDynamicInterface>
इल्या सेमेनोव

जवाबों:


298

हां, आप इसके लिए System.Reflection.Emitनेमस्पेस का उपयोग कर सकते हैं । यदि आपके पास इसके साथ कोई अनुभव नहीं है, तो यह सीधे आगे नहीं है, लेकिन यह निश्चित रूप से संभव है।

संपादित करें: यह कोड त्रुटिपूर्ण हो सकता है, लेकिन यह आपको सामान्य विचार देगा और उम्मीद है कि लक्ष्य की ओर अच्छी शुरुआत करेगा।

using System;
using System.Reflection;
using System.Reflection.Emit;

namespace TypeBuilderNamespace
{
    public static class MyTypeBuilder
    {
        public static void CreateNewObject()
        {
            var myType = CompileResultType();
            var myObject = Activator.CreateInstance(myType);
        }
        public static Type CompileResultType()
        {
            TypeBuilder tb = GetTypeBuilder();
            ConstructorBuilder constructor = tb.DefineDefaultConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName);

            // NOTE: assuming your list contains Field objects with fields FieldName(string) and FieldType(Type)
            foreach (var field in yourListOfFields)
                CreateProperty(tb, field.FieldName, field.FieldType);

            Type objectType = tb.CreateType();
            return objectType;
        }

        private static TypeBuilder GetTypeBuilder()
        {
            var typeSignature = "MyDynamicType";
            var an = new AssemblyName(typeSignature);
            AssemblyBuilder assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run);
            ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");
            TypeBuilder tb = moduleBuilder.DefineType(typeSignature,
                    TypeAttributes.Public |
                    TypeAttributes.Class |
                    TypeAttributes.AutoClass |
                    TypeAttributes.AnsiClass |
                    TypeAttributes.BeforeFieldInit |
                    TypeAttributes.AutoLayout,
                    null);
            return tb;
        }

        private static void CreateProperty(TypeBuilder tb, string propertyName, Type propertyType)
        {
            FieldBuilder fieldBuilder = tb.DefineField("_" + propertyName, propertyType, FieldAttributes.Private);

            PropertyBuilder propertyBuilder = tb.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, null);
            MethodBuilder getPropMthdBldr = tb.DefineMethod("get_" + propertyName, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, propertyType, Type.EmptyTypes);
            ILGenerator getIl = getPropMthdBldr.GetILGenerator();

            getIl.Emit(OpCodes.Ldarg_0);
            getIl.Emit(OpCodes.Ldfld, fieldBuilder);
            getIl.Emit(OpCodes.Ret);

            MethodBuilder setPropMthdBldr =
                tb.DefineMethod("set_" + propertyName,
                  MethodAttributes.Public |
                  MethodAttributes.SpecialName |
                  MethodAttributes.HideBySig,
                  null, new[] { propertyType });

            ILGenerator setIl = setPropMthdBldr.GetILGenerator();
            Label modifyProperty = setIl.DefineLabel();
            Label exitSet = setIl.DefineLabel();

            setIl.MarkLabel(modifyProperty);
            setIl.Emit(OpCodes.Ldarg_0);
            setIl.Emit(OpCodes.Ldarg_1);
            setIl.Emit(OpCodes.Stfld, fieldBuilder);

            setIl.Emit(OpCodes.Nop);
            setIl.MarkLabel(exitSet);
            setIl.Emit(OpCodes.Ret);

            propertyBuilder.SetGetMethod(getPropMthdBldr);
            propertyBuilder.SetSetMethod(setPropMthdBldr);
        }
    }
}

2
बहुत बढ़िया!! क्या आप मुझे यह भी बता सकते हैं कि CompileResultType () विधि द्वारा लौटाए गए प्रकार का ऑब्जेक्ट कैसे बनाया जाए?
अश्वनाचार्य

4
आप उसके लिए System.Activator का उपयोग कर सकते हैं। मैं एक उदाहरण के साथ उत्तर को अपडेट करूंगा।
डेनिजल्स

4
ध्यान दें कि आपको अपने गतिशील प्रकार में फ़ील्ड्स की जांच, पढ़ने और अपडेट करने के लिए प्रतिबिंब का उपयोग करना होगा। यदि आप इंटेलीसेन्स चाहते हैं और कोई प्रतिबिंब नहीं है, तो आपके पास एक स्थिर आधार वर्ग या इंटरफ़ेस होना चाहिए जो आपके डायनेमिक क्लास से विरासत में मिला है और जिसे डाला जा सकता है। उस स्थिति में आप GetTypeBuilder () पद्धति को संशोधित कर सकते हैं और पिछले पैरामीटर के रूप में स्थिर प्रकार को शामिल करने के लिए मॉड्यूल Builder.DefineType कॉल को बदल सकते हैं (अभी रिक्त है)
danijels

2
क्या कोई इसके निर्माण के बाद वस्तु का उपयोग करने का तरीका बता सकता है
HELP_ME

3
@bugz क्लास बनाने के लिए ऊपर दिए गए कोड का उपयोग करें, फिर बेस क्लास में आप इस विधि को जोड़ सकते हैं: public void SetValue <T> (string name, T value) {GetType ()। GetProperty (नाम) .SetValue (यह, मान) ); }
stricq

71

यह कुछ काम लेगा, लेकिन निश्चित रूप से असंभव नहीं है।

मैंने क्या किया है:

  • स्ट्रिंग में C # स्रोत बनाएं (फ़ाइल में लिखने की आवश्यकता नहीं है),
  • इसे Microsoft.CSharp.CSharpCodeProvider(CompileAssemblyFromSource) के माध्यम से चलाएँ
  • उत्पन्न प्रकार का पता लगाएं
  • और उस प्रकार का एक उदाहरण बनाएं ( Activator.CreateInstance)

इस तरह से आप MSIL का उत्सर्जन करने के बजाय अपने द्वारा पहले से ज्ञात C # कोड से निपट सकते हैं।

लेकिन यह सबसे अच्छा काम करता है यदि आपकी कक्षा कुछ इंटरफ़ेस को लागू करती है (या कुछ बेसकेल्स से ली गई है), अन्यथा कॉलिंग कोड (रीड: कंपाइलर) उस वर्ग के बारे में जानने के लिए कैसे है जो रनटाइम पर उत्पन्न होगा?


7
इस चर्चा को देखने के लिए चाहते हो सकता है: प्रतिबिंब-फेंकना-बनाम-codedom
nawfal

1
@nawfal, ashwnacharya, मूल रूप से एक सूची में शामिल अपने सदस्यों के साथ अपनी कक्षा के दौरान गतिशील रूप से उत्पन्न करना चाहता था। मुझे नहीं लगता कि रनटाइम पर उत्पन्न फ़ाइल में इसे डालना एक अच्छा प्रदर्शन समाधान होगा।
sodjsn26fr

39

तुम भी गतिशील रूप से उपयोग करके कक्षा में बना सकते हैं DynamicObject

public class DynamicClass : DynamicObject
{
    private Dictionary<string, KeyValuePair<Type, object>> _fields;

    public DynamicClass(List<Field> fields)
    {
        _fields = new Dictionary<string, KeyValuePair<Type, object>>();
        fields.ForEach(x => _fields.Add(x.FieldName,
            new KeyValuePair<Type, object>(x.FieldType, null)));
    }

    public override bool TrySetMember(SetMemberBinder binder, object value)
    {
        if (_fields.ContainsKey(binder.Name))
        {
            var type = _fields[binder.Name].Key;
            if (value.GetType() == type)
            {
                _fields[binder.Name] = new KeyValuePair<Type, object>(type, value);
                return true;
            }
            else throw new Exception("Value " + value + " is not of type " + type.Name);
        }
        return false;
    }

    public override bool TryGetMember(GetMemberBinder binder, out object result)
    {
        result = _fields[binder.Name].Value;
        return true;
    }
}

मैं सभी प्रकार के क्षेत्रों _fieldsको उनके प्रकारों और मूल्यों के साथ एक शब्दकोश में संग्रहीत करता हूं । दोनों तरीकों में से कुछ गुणों को मूल्य प्राप्त करना या सेट करना है। dynamicइस वर्ग का उदाहरण बनाने के लिए आपको कीवर्ड का उपयोग करना चाहिए ।

आपके उदाहरण के साथ उपयोग:

var fields = new List<Field>() { 
    new Field("EmployeeID", typeof(int)),
    new Field("EmployeeName", typeof(string)),
    new Field("Designation", typeof(string)) 
};

dynamic obj = new DynamicClass(fields);

//set
obj.EmployeeID = 123456;
obj.EmployeeName = "John";
obj.Designation = "Tech Lead";

obj.Age = 25;             //Exception: DynamicClass does not contain a definition for 'Age'
obj.EmployeeName = 666;   //Exception: Value 666 is not of type String

//get
Console.WriteLine(obj.EmployeeID);     //123456
Console.WriteLine(obj.EmployeeName);   //John
Console.WriteLine(obj.Designation);    //Tech Lead

संपादित करें: और यहाँ है कि मेरी कक्षा कैसी दिखती है Field:

public class Field
{
    public Field(string name, Type type)
    {
        this.FieldName = name;
        this.FieldType = type;
    }

    public string FieldName;

    public Type FieldType;
}

1
मुझे इस दृष्टिकोण को पसंद आया जब तक मुझे निर्माणकर्ता के साथ खेतों को शुरू करने की आवश्यकता नहीं थी। यानी dynamic obj = new DynamicClass(fields){EmployeeId=123456;EmployeeName = "John"; Designation = "Tech Lead";}यह वास्तव में बहुत अच्छा होगा।
rey_coder

14

मुझे इस तरह के गतिशील वर्गों, और कोड पीढ़ी और रन टाइम संकलन का इरादा उपयोग नहीं पता है, लेकिन कुछ प्रयास करता है। शायद बेनामी प्रकार आपकी मदद करेंगे, कुछ इस तरह:

var v = new { EmployeeID = 108, EmployeeName = "John Doe" };

7
आप फ़ील्ड नामों को हार्ड कोड नहीं कर सकते। वह उन्हें अपने साथ प्रदान कर रहा है Field.FieldName। हार्ड कोड होने के कारण क्षेत्र के नाम उद्देश्य को हरा देते हैं। यदि आपको ऐसा करना है, तो आप कक्षा भी बना सकते हैं।
toddmo

14

मुझे पता है कि मैं इस पुराने कार्य को फिर से खोल रहा हूं लेकिन c # 4.0 के साथ यह कार्य बिल्कुल दर्द रहित है।

dynamic expando = new ExpandoObject();
expando.EmployeeID=42;
expando.Designation="unknown";
expando.EmployeeName="curt"

//or more dynamic
AddProperty(expando, "Language", "English");

अधिक जानकारी के लिए https://www.oreilly.com/learning/building-c-objects-dynamically देखें


हाँ, लेकिन आप यहाँ सुरक्षा खो देते हैं। क्या हम प्रकार की सुरक्षा को संरक्षित करते हुए कुछ ऐसा कर सकते हैं?
कठिन संयोग

9

आप कोडडॉम को देखना चाहते हैं । यह कोड तत्वों को परिभाषित करने और उन्हें संकलित करने की अनुमति देता है। MSDN का हवाला देते हुए:

... इस ऑब्जेक्ट ग्राफ को एक समर्थित प्रोग्रामिंग भाषा के लिए कोडडॉम कोड जनरेटर का उपयोग करके स्रोत कोड के रूप में प्रस्तुत किया जा सकता है। कोडडॉम का उपयोग स्रोत कोड को बाइनरी असेंबली में संकलित करने के लिए भी किया जा सकता है।


मैं चाहता हूं कि यह रनटाइम में उत्पन्न हो। मैं अपने फाइल सिस्टम में एक भौतिक सीएस फ़ाइल नहीं चाहता। पहले उल्लेख नहीं करने के लिए क्षमा करें।
अश्वनाचार्य

1
@ यशवनाचार्य: आप सोर्स फाइल तैयार करने और इसे रनटाइम पर संकलन करने के लिए कोडडॉम का उपयोग कर सकते हैं!
हेमंत

1
हालांकि, खबरदार है कि कोडडोम कंपाइलर एक कच्ची स्ट्रिंग लेता है, और इस तरह आप एक्सएसएस और एसक्यूएल इंजेक्शन में उपयोग किए जाने वाले समान "कोड सम्मिलन हमलों" पर विचार करना चाह सकते हैं।
9

6

@ Danijels के उत्तर के आधार पर, VB.NET में गतिशील रूप से एक कक्षा बनाएँ:

Imports System.Reflection
Imports System.Reflection.Emit

Public Class ObjectBuilder

Public Property myType As Object
Public Property myObject As Object

Public Sub New(fields As List(Of Field))
    myType = CompileResultType(fields)
    myObject = Activator.CreateInstance(myType)
End Sub

Public Shared Function CompileResultType(fields As List(Of Field)) As Type
    Dim tb As TypeBuilder = GetTypeBuilder()
    Dim constructor As ConstructorBuilder = tb.DefineDefaultConstructor(MethodAttributes.[Public] Or MethodAttributes.SpecialName Or MethodAttributes.RTSpecialName)

    For Each field In fields
        CreateProperty(tb, field.Name, field.Type)
    Next

    Dim objectType As Type = tb.CreateType()
    Return objectType
End Function

Private Shared Function GetTypeBuilder() As TypeBuilder
    Dim typeSignature = "MyDynamicType"
    Dim an = New AssemblyName(typeSignature)
    Dim assemblyBuilder As AssemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run)
    Dim moduleBuilder As ModuleBuilder = assemblyBuilder.DefineDynamicModule("MainModule")
    Dim tb As TypeBuilder = moduleBuilder.DefineType(typeSignature, TypeAttributes.[Public] Or TypeAttributes.[Class] Or TypeAttributes.AutoClass Or TypeAttributes.AnsiClass Or TypeAttributes.BeforeFieldInit Or TypeAttributes.AutoLayout, Nothing)
    Return tb
End Function

Private Shared Sub CreateProperty(tb As TypeBuilder, propertyName As String, propertyType As Type)
    Dim fieldBuilder As FieldBuilder = tb.DefineField("_" & propertyName, propertyType, FieldAttributes.[Private])

    Dim propertyBuilder As PropertyBuilder = tb.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, Nothing)
    Dim getPropMthdBldr As MethodBuilder = tb.DefineMethod("get_" & propertyName, MethodAttributes.[Public] Or MethodAttributes.SpecialName Or MethodAttributes.HideBySig, propertyType, Type.EmptyTypes)
    Dim getIl As ILGenerator = getPropMthdBldr.GetILGenerator()

    getIl.Emit(OpCodes.Ldarg_0)
    getIl.Emit(OpCodes.Ldfld, fieldBuilder)
    getIl.Emit(OpCodes.Ret)

    Dim setPropMthdBldr As MethodBuilder = tb.DefineMethod("set_" & propertyName, MethodAttributes.[Public] Or MethodAttributes.SpecialName Or MethodAttributes.HideBySig, Nothing, {propertyType})

    Dim setIl As ILGenerator = setPropMthdBldr.GetILGenerator()
    Dim modifyProperty As Label = setIl.DefineLabel()
    Dim exitSet As Label = setIl.DefineLabel()

    setIl.MarkLabel(modifyProperty)
    setIl.Emit(OpCodes.Ldarg_0)
    setIl.Emit(OpCodes.Ldarg_1)
    setIl.Emit(OpCodes.Stfld, fieldBuilder)

    setIl.Emit(OpCodes.Nop)
    setIl.MarkLabel(exitSet)
    setIl.Emit(OpCodes.Ret)

    propertyBuilder.SetGetMethod(getPropMthdBldr)
    propertyBuilder.SetSetMethod(setPropMthdBldr)
End Sub

End Class

6

आप डायनामिक रूप से डायनामिक एक्सपेरिमेंट्स का उपयोग करके एक वर्ग भी बना सकते हैं ।

चूँकि 'डिक्शनरी में कॉम्पैक्ट इनिशियलाइज़र्स होते हैं और प्रमुख टक्करों को संभालते हैं, इसलिए आप ऐसा कुछ करना चाहेंगे।

  var list = new Dictionary<string, string> {
    {
      "EmployeeID",
      "int"
    }, {
      "EmployeeName",
      "String"
    }, {
      "Birthday",
      "DateTime"
    }
  };

या आप अपने क्रमबद्ध स्ट्रिंग ऑब्जेक्ट को कुछ प्रबंधनीय बनाने के लिए JSON कन्वर्टर का उपयोग करना चाह सकते हैं।

फिर System.Linq.Dynamic का उपयोग करना;

  IEnumerable<DynamicProperty> props = list.Select(property => new DynamicProperty(property.Key, Type.GetType(property.Value))).ToList();

  Type t = DynamicExpression.CreateClass(props);

बाकी सिर्फ़ System.Reflection का उपयोग कर रहा है।

  object obj = Activator.CreateInstance(t);
  t.GetProperty("EmployeeID").SetValue(obj, 34, null);
  t.GetProperty("EmployeeName").SetValue(obj, "Albert", null);
  t.GetProperty("Birthday").SetValue(obj, new DateTime(1976, 3, 14), null);
}  

4

उन लोगों के लिए जो डायनेमिक क्लास बस प्रॉपर्टीज (यानी POCO) बनाना चाहते हैं, और इस क्लास की लिस्ट बनाएं। बाद में प्रदान किए गए कोड का उपयोग करते हुए, यह एक गतिशील वर्ग बनाएगा और इसकी एक सूची बनाएगा।

var properties = new List<DynamicTypeProperty>()
{
    new DynamicTypeProperty("doubleProperty", typeof(double)),
    new DynamicTypeProperty("stringProperty", typeof(string))
};

// create the new type
var dynamicType = DynamicType.CreateDynamicType(properties);
// create a list of the new type
var dynamicList = DynamicType.CreateDynamicList(dynamicType);

// get an action that will add to the list
var addAction = DynamicType.GetAddAction(dynamicList);

// call the action, with an object[] containing parameters in exact order added
addAction.Invoke(new object[] {1.1, "item1"});
addAction.Invoke(new object[] {2.1, "item2"});
addAction.Invoke(new object[] {3.1, "item3"});

यहां वे कक्षाएं हैं जिनका पिछला कोड उपयोग करता है।

नोट: आपको Microsoft.CodeAnalysis.CSharp लाइब्रेरी का संदर्भ भी देना होगा।

       /// <summary>
    /// A property name, and type used to generate a property in the dynamic class.
    /// </summary>
    public class DynamicTypeProperty
    {
        public DynamicTypeProperty(string name, Type type)
        {
            Name = name;
            Type = type;
        }
        public string Name { get; set; }
        public Type Type { get; set; }
    }

   public static class DynamicType
    {
        /// <summary>
        /// Creates a list of the specified type
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public static IEnumerable<object> CreateDynamicList(Type type)
        {
            var listType = typeof(List<>);
            var dynamicListType = listType.MakeGenericType(type);
            return (IEnumerable<object>) Activator.CreateInstance(dynamicListType);
        }

        /// <summary>
        /// creates an action which can be used to add items to the list
        /// </summary>
        /// <param name="listType"></param>
        /// <returns></returns>
        public static Action<object[]> GetAddAction(IEnumerable<object> list)
        {
            var listType = list.GetType();
            var addMethod = listType.GetMethod("Add");
            var itemType = listType.GenericTypeArguments[0];
            var itemProperties = itemType.GetProperties();

            var action = new Action<object[]>((values) =>
            {
                var item = Activator.CreateInstance(itemType);

                for(var i = 0; i < values.Length; i++)
                {
                    itemProperties[i].SetValue(item, values[i]);
                }

                addMethod.Invoke(list, new []{item});
            });

            return action;
        }

        /// <summary>
        /// Creates a type based on the property/type values specified in the properties
        /// </summary>
        /// <param name="properties"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static Type CreateDynamicType(IEnumerable<DynamicTypeProperty> properties)
        {
            StringBuilder classCode = new StringBuilder();

            // Generate the class code
            classCode.AppendLine("using System;");
            classCode.AppendLine("namespace Dexih {");
            classCode.AppendLine("public class DynamicClass {");

            foreach (var property in properties)
            {
                classCode.AppendLine($"public {property.Type.Name} {property.Name} {{get; set; }}");
            }
            classCode.AppendLine("}");
            classCode.AppendLine("}");

            var syntaxTree = CSharpSyntaxTree.ParseText(classCode.ToString());

            var references = new MetadataReference[]
            {
                MetadataReference.CreateFromFile(typeof(object).GetTypeInfo().Assembly.Location),
                MetadataReference.CreateFromFile(typeof(DictionaryBase).GetTypeInfo().Assembly.Location)
            };

            var compilation = CSharpCompilation.Create("DynamicClass" + Guid.NewGuid() + ".dll",
                syntaxTrees: new[] {syntaxTree},
                references: references,
                options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));

            using (var ms = new MemoryStream())
            {
                var result = compilation.Emit(ms);

                if (!result.Success)
                {
                    var failures = result.Diagnostics.Where(diagnostic =>
                        diagnostic.IsWarningAsError ||
                        diagnostic.Severity == DiagnosticSeverity.Error);

                    var message = new StringBuilder();

                    foreach (var diagnostic in failures)
                    {
                        message.AppendFormat("{0}: {1}", diagnostic.Id, diagnostic.GetMessage());
                    }

                    throw new Exception($"Invalid property definition: {message}.");
                }
                else
                {

                    ms.Seek(0, SeekOrigin.Begin);
                    var assembly = System.Runtime.Loader.AssemblyLoadContext.Default.LoadFromStream(ms);
                    var dynamicType = assembly.GetType("Dexih.DynamicClass");
                    return dynamicType;
                }
            }
        }
    }

कोड का बड़ा टुकड़ा। डायनेमिक सूची में भी AddRange का उपयोग करना संभव होगा, अंततः एक बार में कई रिकॉर्ड जोड़ने के लिए?
रिकीटाड

2

आप गतिशील मॉड्यूल और कक्षाओं का उपयोग करके देख सकते हैं जो काम कर सकते हैं। एकमात्र नुकसान यह है कि यह ऐप डोमेन में लोड रहता है। लेकिन .NET फ्रेमवर्क के संस्करण का उपयोग किया जा रहा है, जो बदल सकता है। .NET 4.0 संग्रहणीय डायनेमिक असेंबली का समर्थन करता है और इसलिए आप कक्षाओं / प्रकारों को गतिशील रूप से फिर से बना सकते हैं।


2

वाह! उस उत्तर के लिए धन्यवाद! मैंने इसमें कुछ विशेषताएं जोड़ीं, ताकि मैं आपके साथ साझा करने के लिए "डिटेंबल टू जसन" कन्वर्टर बना सकूं।

    Public Shared Sub dt2json(ByVal _dt As DataTable, ByVal _sb As StringBuilder)
    Dim t As System.Type

    Dim oList(_dt.Rows.Count - 1) As Object
    Dim jss As New JavaScriptSerializer()
    Dim i As Integer = 0

    t = CompileResultType(_dt)

    For Each dr As DataRow In _dt.Rows
        Dim o As Object = Activator.CreateInstance(t)

        For Each col As DataColumn In _dt.Columns
            setvalue(o, col.ColumnName, dr.Item(col.ColumnName))
        Next

        oList(i) = o
        i += 1
    Next

    jss = New JavaScriptSerializer()
    jss.Serialize(oList, _sb)


End Sub

और "compileresulttype" उप में, मैंने उसे बदल दिया:

    For Each column As DataColumn In _dt.Columns
        CreateProperty(tb, column.ColumnName, column.DataType)
    Next


Private Shared Sub setvalue(ByVal _obj As Object, ByVal _propName As String, ByVal _propValue As Object)
    Dim pi As PropertyInfo
    pi = _obj.GetType.GetProperty(_propName)
    If pi IsNot Nothing AndAlso pi.CanWrite Then
        If _propValue IsNot DBNull.Value Then
            pi.SetValue(_obj, _propValue, Nothing)

        Else
            Select Case pi.PropertyType.ToString
                Case "System.String"
                    pi.SetValue(_obj, String.Empty, Nothing)
                Case Else
                    'let the serialiser use javascript "null" value.
            End Select

        End If
    End If

End Sub

0

आप System.Runtime.Remoting.Proxies.RealProxy का उपयोग कर सकते हैं। यह आपको निम्न स्तर के विधानसभा प्रकार के सामान के बजाय "सामान्य" कोड का उपयोग करने की अनुमति देगा।

एक अच्छे उदाहरण के लिए इस सवाल का RealProxy जवाब देखें:

मैं C # में विधि कॉल को कैसे रोकूं?


-1

Runtime Code Generation with JVM and CLR - पीटर सेस्टॉफ्ट

ऐसे व्यक्तियों के लिए काम करें जो वास्तव में इस प्रकार की प्रोग्रामिंग में रुचि रखते हैं।

आपके लिए मेरी टिप यह है कि यदि आप घोषित करते हैं कि कुछ स्ट्रिंग से बचने की कोशिश करते हैं, तो यदि आपके पास क्लास फील्ड है तो क्लास सिस्टम का उपयोग करना बेहतर है । स्ट्रिंग से फ़ील्ड प्रकार को स्टोर करने के लिए टाइप करें। और सृजन के लिए सर्वश्रेष्ठ समाधानों के बजाय नई कक्षाएं उन लोगों का उपयोग करने की कोशिश करती हैं जिन्हें नए निर्माण के बजाय FiledInfo बनाया गया है ।


2
लिंक मर चुका है: -1
ग्लेन स्लेडेन

ग्लेन: एक त्वरित googling ने एक कामकाजी लिंक का खुलासा किया: pdfs.semanticscholar.org/326a/…
एंड्रियास परडेइक

@AndreasPardeike धन्यवाद, मैंने लेख में इसकी मरम्मत की।
ग्लेन स्लेडेन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.