Wie erstelle ich dynamisch eine Klasse?


221

Ich habe eine Klasse, die so aussieht:

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

Und ein Objekt List<Field>mit Werten:

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

Ich möchte eine Klasse erstellen, die so aussieht:

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

Gibt es eine Möglichkeit, dies zu tun?

Ich möchte, dass dies zur Laufzeit generiert wird. Ich möchte keine physische CS-Datei in meinem Dateisystem.


4
Möchten Sie diese Klasse zur Laufzeit verwenden oder nur eine Datei generieren?
Damian Leszczyński - Vash

Ich möchte, dass dies zur Laufzeit generiert wird. Ich möchte keine physische CS-Datei in meinem Dateisystem. Tut mir leid, dass ich das nicht früher erwähnt habe.
Ashwnacharya

16
Können Sie uns eine grobe Vorstellung von dem, was wollen Sie zu tun , mit dieser Klasse?
Justin

3
@Justin implementiert beispielsweise zur Laufzeit aufgelöste Schnittstellen.
AgentFire

Man könnte es fütternSystem.ServiceModel.ChannelFactory<MyDynamicInterface>
Ilya Semenov

Antworten:


297

Ja, Sie können hierfür den System.Reflection.EmitNamespace verwenden. Es ist nicht einfach, wenn Sie keine Erfahrung damit haben, aber es ist sicherlich möglich.

Bearbeiten: Dieser Code ist möglicherweise fehlerhaft, aber er gibt Ihnen die allgemeine Vorstellung und hoffentlich einen guten Start in Richtung Ziel.

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
Genial!! Können Sie mir auch sagen, wie ein Objekt des Typs erstellt wird, der von der CompileResultType () -Methode zurückgegeben wird?
Ashwnacharya

4
Sie können dafür System.Activator verwenden. Ich werde die Antwort mit einem Beispiel aktualisieren.
danijels

4
Beachten Sie auch, dass Sie Reflection verwenden müssen, um Felder in Ihrem dynamischen Typ zu untersuchen, zu lesen und zu aktualisieren. Wenn Sie Intellisense und keine Reflexion wünschen, müssen Sie über eine statische Basisklasse oder Schnittstelle verfügen, von der Ihre dynamische Klasse erbt und in die sie umgewandelt werden kann. In diesem Fall können Sie die GetTypeBuilder () -Methode ändern und den Aufruf moduleBuilder.DefineType so ändern, dass der statische Typ als letzter Parameter eingeschlossen wird (ist jetzt null)
danijels

2
kann jemand erklären, wie man das Objekt nach seiner
Erstellung verwendet

3
@bugz Verwenden Sie den obigen Code, um die Klasse zu erstellen. In der Basisklasse können Sie diese Methode hinzufügen: public void SetValue <T> (Zeichenfolgenname, T-Wert) {GetType (). GetProperty (Name) .SetValue (dieser Wert ); }
stricq

71

Es wird einige Arbeit erfordern, ist aber sicherlich nicht unmöglich.

Was ich getan habe ist:

  • Erstellen Sie eine C # -Quelle in einer Zeichenfolge (Sie müssen nicht in eine Datei schreiben).
  • Führen Sie es durch die Microsoft.CSharp.CSharpCodeProvider (CompileAssemblyFromSource)
  • Suchen Sie den generierten Typ
  • Und erstellen Sie eine Instanz dieses Typs ( Activator.CreateInstance)

Auf diese Weise können Sie mit dem bereits bekannten C # -Code umgehen, anstatt MSIL ausgeben zu müssen.

Dies funktioniert jedoch am besten, wenn Ihre Klasse eine Schnittstelle implementiert (oder von einer Basisklasse abgeleitet ist). Wie kann der aufrufende Code (read: compiler) über diese Klasse Bescheid wissen, die zur Laufzeit generiert wird?


7
Vielleicht möchten Sie diese Diskussion sehen: Reflection-Emit-vs-Codedom
Nawfal

1
@nawfal, ashwnacharya, wollte zur Laufzeit dynamisch seine Klasse mit seinen ursprünglich in einer Liste enthaltenen Mitgliedern generieren. Ich denke nicht, dass das Einfügen in eine Datei, die selbst zur Laufzeit generiert wurde, eine gute Leistungslösung wäre.
sodjsn26fr

38

Sie können eine Klasse auch dynamisch mithilfe von DynamicObject erstellen .

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

Ich speichere alle Klassenfelder _fieldszusammen mit ihren Typen und Werten in einem Wörterbuch . Mit beiden Methoden können einige der Eigenschaften abgerufen oder festgelegt werden. Sie müssen das dynamicSchlüsselwort verwenden, um eine Instanz dieser Klasse zu erstellen.

Die Verwendung mit Ihrem Beispiel:

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

Edit: Und so sieht meine Klasse aus Field:

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

    public string FieldName;

    public Type FieldType;
}

1
Ich mochte diesen Ansatz, bis ich die Felder mit dem Konstruktor initialisieren musste. dh dynamic obj = new DynamicClass(fields){EmployeeId=123456;EmployeeName = "John"; Designation = "Tech Lead";}es wäre wirklich toll das zu tun.
rey_coder

14

Ich weiß, dass ich diese alte Aufgabe wieder öffne, aber mit c # 4.0 ist diese Aufgabe absolut schmerzlos.

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

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

Weitere Informationen finden Sie unter https://www.oreilly.com/learning/building-c-objects-dynamically


Ja, aber Sie verlieren hier die Typensicherheit. Können wir etwas Ähnliches tun, während die Typensicherheit erhalten bleibt?
harte Fragen

13

Ich kenne die beabsichtigte Verwendung solcher dynamischer Klassen nicht, und die Codegenerierung und Laufzeitkompilierung kann durchgeführt werden, erfordert jedoch einige Anstrengungen. Vielleicht würden Ihnen anonyme Typen helfen, so etwas wie:

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

7
Sie können die Feldnamen nicht fest codieren. Er versorgt sie mit seinem Field.FieldName. Die Feldnamen hart codieren zu müssen, macht den Zweck zunichte. Wenn Sie das tun müssen, können Sie auch die Klasse erstellen.
Toddmo

9

Sie möchten sich CodeDOM ansehen . Es ermöglicht das Definieren und Kompilieren von Codeelementen. MSDN zitieren:

... Dieses Objektdiagramm kann mit einem CodeDOM-Codegenerator für eine unterstützte Programmiersprache als Quellcode gerendert werden. Das CodeDOM kann auch verwendet werden, um Quellcode in eine binäre Assembly zu kompilieren.


Ich möchte, dass dies zur Laufzeit generiert wird. Ich möchte keine physische CS-Datei in meinem Dateisystem. Tut mir leid, dass ich das nicht früher erwähnt habe.
Ashwnacharya

1
@ashwnacharya: Sie können CodeDOM verwenden, um die Quelldatei zu generieren und zur Laufzeit zu kompilieren!
Hemant

1
Beachten Sie jedoch, dass der CodeDOM-Compiler eine unformatierte Zeichenfolge verwendet. Daher sollten Sie möglicherweise "Angriffe zum Einfügen von Code" in Betracht ziehen, die denen ähneln, die bei der XSS- und SQL-Injection verwendet werden.
Cwap

6

Erstellen Sie basierend auf der Antwort von @ danijels dynamisch eine Klasse in 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

Sie können eine Klasse auch dynamisch mithilfe von DynamicExpressions erstellen .

Da 'Wörterbücher kompakte Initialisierer haben und Schlüsselkollisionen verarbeiten, sollten Sie so etwas tun.

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

Oder Sie möchten möglicherweise einen JSON-Konverter verwenden, um Ihr serialisiertes Zeichenfolgenobjekt in etwas Verwaltbares zu konstruieren.

Verwenden Sie dann System.Linq.Dynamic.

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

  Type t = DynamicExpression.CreateClass(props);

Der Rest verwendet nur 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

Für diejenigen, die eine dynamische Klasse erstellen möchten, nur Eigenschaften (dh POCO) und eine Liste dieser Klasse erstellen. Mit dem später bereitgestellten Code wird eine dynamische Klasse erstellt und eine Liste davon erstellt.

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

Hier sind die Klassen, die der vorherige Code verwendet.

Hinweis: Sie müssen auch auf die Microsoft.CodeAnalysis.CSharp-Bibliothek verweisen.

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

Tolles Stück Code. Wäre es möglich, auch AddRange in der dynamischen Liste zu verwenden, um eventuell mehrere Datensätze gleichzeitig hinzuzufügen?
RickyTad

2

Sie können sich die Verwendung dynamischer Module und Klassen ansehen, die diese Aufgabe erfüllen können. Der einzige Nachteil ist, dass es in der App-Domain geladen bleibt. Mit der verwendeten Version von .NET Framework könnte sich dies jedoch ändern. .NET 4.0 unterstützt sammelbare dynamische Assemblys. Daher können Sie die Klassen / Typen dynamisch neu erstellen.


2

Beeindruckend! Vielen Dank für diese Antwort! Ich habe einige Funktionen hinzugefügt, um einen "datatable to json" -Konverter zu erstellen, den ich mit Ihnen teile.

    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

Und im Sub "compileresulttype" habe ich Folgendes geändert:

    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

Sie können System.Runtime.Remoting.Proxies.RealProxy verwenden. Es ermöglicht Ihnen, "normalen" Code anstelle von Assemblierungsmaterial auf niedriger Ebene zu verwenden.

Ein gutes Beispiel finden Sie in der RealProxy-Antwort auf diese Frage:

Wie fange ich einen Methodenaufruf in C # ab?


-1

Runtime Code Generation with JVM and CLR - Peter Sestoft

Arbeiten Sie für Personen, die sich wirklich für diese Art der Programmierung interessieren.

Mein Tipp für Sie ist, dass Sie, wenn Sie etwas deklarieren, versuchen, eine Zeichenfolge zu vermeiden. Wenn Sie also eine Klasse Field haben, ist es besser, die Klasse System.Type zum Speichern des Feldtyps als eine Zeichenfolge zu verwenden. Und um die besten Lösungen zu erzielen, anstatt neue Klassen zu erstellen, versuchen Sie, diejenigen zu verwenden, die FiledInfo erstellt hat, anstatt neue zu erstellen .


2
Link ist tot: -1
Glenn Slayden

Glenn: Ein kurzes Googeln ergab einen funktionierenden Link: pdfs.semanticscholar.org/326a/…
Andreas Pardeike

@AndreasPardeike Danke, ich habe es im Artikel repariert.
Glenn Slayden
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.