[英]How to dynamically create a class?
I have a class which looks like this:我有一个看起来像这样的课程:
public class Field
{
public string FieldName;
public string FieldType;
}
And an object List<Field>
with values:还有一个带有值的对象
List<Field>
:
{"EmployeeID","int"},
{"EmployeeName","String"},
{"Designation","String"}
I want to create a class that looks like this:我想创建一个如下所示的类:
Class DynamicClass
{
int EmployeeID,
String EmployeeName,
String Designation
}
Is there any way to do this?有没有办法做到这一点?
I want this to be generated at runtime.我希望在运行时生成它。 I don't want a physical CS file residing in my filesystem.
我不希望我的文件系统中存在物理 CS 文件。
Yes, you can use System.Reflection.Emit
namespace for this.是的,您可以为此使用
System.Reflection.Emit
命名空间。 It is not straight forward if you have no experience with it, but it is certainly possible.如果您没有经验,这不是直接的,但它肯定是可能的。
Edit: This code might be flawed, but it will give you the general idea and hopefully off to a good start towards the goal.编辑:这段代码可能有缺陷,但它会给你一个大致的想法,并希望有一个朝着目标的良好开端。
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);
}
}
}
It will take some work, but is certainly not impossible.这需要一些工作,但肯定不是不可能的。
What I have done is:我所做的是:
Microsoft.CSharp.CSharpCodeProvider
(CompileAssemblyFromSource)Microsoft.CSharp.CSharpCodeProvider
(CompileAssemblyFromSource) 运行它Activator.CreateInstance
)Activator.CreateInstance
) This way you can deal with the C# code you already know, instead of having to emit MSIL.这样您就可以处理您已经知道的 C# 代码,而不必发出 MSIL。
But this works best if your class implements some interface (or is derived from some baseclass), else how is the calling code (read: compiler) to know about that class that will be generated at runtime?但是,如果您的类实现了某个接口(或从某个基类派生而来),那么这种方法效果最好,否则调用代码(阅读:编译器)如何知道将在运行时生成的该类?
You can also dynamically create a class by using DynamicObject .您还可以使用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;
}
}
I store all class fields in a dictionary _fields
together with their types and values.我将所有类字段及其类型和值存储在字典
_fields
。 The both methods are to can get or set value to some of the properties.这两种方法都可以获取或设置某些属性的值。 You must use the
dynamic
keyword to create an instance of this class.您必须使用
dynamic
关键字来创建此类的实例。
The usage with your example:您的示例的用法:
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: And here is how looks my class Field
:编辑:这是我的班级
Field
样子:
public class Field
{
public Field(string name, Type type)
{
this.FieldName = name;
this.FieldType = type;
}
public string FieldName;
public Type FieldType;
}
I know i reopen this old task but with c# 4.0 this task is absolutely painless.我知道我重新打开了这个旧任务,但是使用 c# 4.0 这个任务绝对是轻松的。
dynamic expando = new ExpandoObject();
expando.EmployeeID=42;
expando.Designation="unknown";
expando.EmployeeName="curt"
//or more dynamic
AddProperty(expando, "Language", "English");
for more seehttps://www.oreilly.com/learning/building-c-objects-dynamically有关更多信息,请参阅https://www.oreilly.com/learning/building-c-objects-dynamically
I don't know the intended usage of such dynamic classes, and code generation and run time compilation can be done, but takes some effort.我不知道这种动态类的预期用途,代码生成和运行时编译都可以完成,但需要一些努力。 Maybe Anonymous Types would help you, something like:
也许匿名类型会帮助你,比如:
var v = new { EmployeeID = 108, EmployeeName = "John Doe" };
You want to look at CodeDOM .你想看看CodeDOM 。 It allows defining code elements and compiling them.
它允许定义代码元素并编译它们。 Quoting MSDN:
引用 MSDN:
...This object graph can be rendered as source code using a CodeDOM code generator for a supported programming language.
...可以使用支持的编程语言的 CodeDOM 代码生成器将此对象图呈现为源代码。 The CodeDOM can also be used to compile source code into a binary assembly.
CodeDOM 还可用于将源代码编译为二进制程序集。
You can also dynamically create a class by using DynamicExpressions .您还可以使用DynamicExpressions动态创建一个类。
Since 'Dictionary's have compact initializers and handle key collisions, you will want to do something like this.由于 'Dictionary' 具有紧凑的初始值设定项并处理键冲突,您将需要做这样的事情。
var list = new Dictionary<string, string> {
{
"EmployeeID",
"int"
}, {
"EmployeeName",
"String"
}, {
"Birthday",
"DateTime"
}
};
Or you might want to use a JSON converter to construct your serialized string object into something manageable.或者,您可能希望使用 JSON 转换器将序列化字符串对象构造为可管理的对象。
Then using System.Linq.Dynamic;然后使用 System.Linq.Dynamic;
IEnumerable<DynamicProperty> props = list.Select(property => new DynamicProperty(property.Key, Type.GetType(property.Value))).ToList();
Type t = DynamicExpression.CreateClass(props);
The rest is just using System.Reflection.剩下的就是使用 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);
}
Based on @danijels's answer, dynamically create a class in VB.NET:根据@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
For those wanting to create a dynamic class just properties (ie POCO), and create a list of this class.对于那些想要创建动态类的只是属性(即 POCO),并创建此类的列表。 Using the code provided later, this will create a dynamic class and create a list of this.
使用稍后提供的代码,这将创建一个动态类并创建一个列表。
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"});
Here are the classes that the previous code uses.下面是前面的代码使用的类。
Note: You'll also need to reference the Microsoft.CodeAnalysis.CSharp library.注意:您还需要引用 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;
}
}
}
}
As Hans suggested, you can use Roslyn to dynamically create classes.正如Hans 所建议的,您可以使用 Roslyn 来动态创建类。
Full source:完整来源:
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
namespace RoslynDemo1
{
class Program
{
static void Main(string[] args)
{
var fields = new List<Field>()
{
new Field("EmployeeID","int"),
new Field("EmployeeName","String"),
new Field("Designation","String")
};
var employeeClass = CreateClass(fields, "Employee");
dynamic employee1 = Activator.CreateInstance(employeeClass);
employee1.EmployeeID = 4213;
employee1.EmployeeName = "Wendy Tailor";
employee1.Designation = "Engineering Manager";
dynamic employee2 = Activator.CreateInstance(employeeClass);
employee2.EmployeeID = 3510;
employee2.EmployeeName = "John Gibson";
employee2.Designation = "Software Engineer";
Console.WriteLine($"{employee1.EmployeeName}");
Console.WriteLine($"{employee2.EmployeeName}");
Console.WriteLine("Press any key to continue...");
Console.ReadKey();
}
public static Type CreateClass(List<Field> fields, string newClassName, string newNamespace = "Magic")
{
var fieldsCode = fields
.Select(field => $"public {field.FieldType} {field.FieldName};")
.ToString(Environment.NewLine);
var classCode = $@"
using System;
namespace {newNamespace}
{{
public class {newClassName}
{{
public {newClassName}()
{{
}}
{fieldsCode}
}}
}}
".Trim();
classCode = FormatUsingRoslyn(classCode);
var assemblies = new[]
{
MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
};
/*
var assemblies = AppDomain
.CurrentDomain
.GetAssemblies()
.Where(a => !string.IsNullOrEmpty(a.Location))
.Select(a => MetadataReference.CreateFromFile(a.Location))
.ToArray();
*/
var syntaxTree = CSharpSyntaxTree.ParseText(classCode);
var compilation = CSharpCompilation
.Create(newNamespace)
.AddSyntaxTrees(syntaxTree)
.AddReferences(assemblies)
.WithOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
using (var ms = new MemoryStream())
{
var result = compilation.Emit(ms);
//compilation.Emit($"C:\\Temp\\{newNamespace}.dll");
if (result.Success)
{
ms.Seek(0, SeekOrigin.Begin);
Assembly assembly = Assembly.Load(ms.ToArray());
var newTypeFullName = $"{newNamespace}.{newClassName}";
var type = assembly.GetType(newTypeFullName);
return type;
}
else
{
IEnumerable<Diagnostic> failures = result.Diagnostics.Where(diagnostic =>
diagnostic.IsWarningAsError ||
diagnostic.Severity == DiagnosticSeverity.Error);
foreach (Diagnostic diagnostic in failures)
{
Console.Error.WriteLine("{0}: {1}", diagnostic.Id, diagnostic.GetMessage());
}
return null;
}
}
}
public static string FormatUsingRoslyn(string csCode)
{
var tree = CSharpSyntaxTree.ParseText(csCode);
var root = tree.GetRoot().NormalizeWhitespace();
var result = root.ToFullString();
return result;
}
}
public class Field
{
public string FieldName;
public string FieldType;
public Field(string fieldName, string fieldType)
{
FieldName = fieldName;
FieldType = fieldType;
}
}
public static class Extensions
{
public static string ToString(this IEnumerable<string> list, string separator)
{
string result = string.Join(separator, list);
return result;
}
}
}
You can look at using dynamic modules and classes that can do the job.您可以查看使用可以完成这项工作的动态模块和类。 The only disadvantage is that it remains loaded in the app domain.
唯一的缺点是它仍然在应用程序域中加载。 But with the version of .NET framework being used, that could change.
但是随着 .NET 框架版本的使用,这可能会改变。 .NET 4.0 supports collectible dynamic assemblies and hence you can recreate the classes/types dynamically.
.NET 4.0 支持可收集的动态程序集,因此您可以动态地重新创建类/类型。
Wow!哇! Thank you for that answer!
谢谢你的回答! I added some features to it to create a "datatable to json" converter that I share with you.
我向它添加了一些功能来创建一个“数据表到 json”转换器,与您分享。
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
And in "compileresulttype" sub, I changed that:在“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
you can use CSharpProvider:您可以使用 CSharpProvider:
var code = @"
public class Abc {
public string Get() { return ""abc""; }
}
";
var options = new CompilerParameters();
options.GenerateExecutable = false;
options.GenerateInMemory = false;
var provider = new CSharpCodeProvider();
var compile = provider.CompileAssemblyFromSource(options, code);
var type = compile.CompiledAssembly.GetType("Abc");
var abc = Activator.CreateInstance(type);
var method = type.GetMethod("Get");
var result = method.Invoke(abc, null);
Console.WriteLine(result); //output: abc
You can use System.Runtime.Remoting.Proxies.RealProxy.您可以使用 System.Runtime.Remoting.Proxies.RealProxy。 It will allow you to use "normal" code rather than low level assembly type stuff.
它将允许您使用“普通”代码而不是低级程序集类型的东西。
See the RealProxy answer to this question for a good example:请参阅 RealProxy 对此问题的回答以获取一个很好的示例:
Runtime Code Generation with JVM and CLR
- Peter Sestoft Runtime Code Generation with JVM and CLR
- Peter Setoft
Work for persons that are really interested in this type of programming.为真正对此类编程感兴趣的人工作。
My tip for You is that if You declare something try to avoid string, so if You have class Field it is better to use class System.Type to store the field type than a string.我给你的提示是,如果你声明一些东西尽量避免字符串,所以如果你有类 Field 最好使用类System.Type来存储字段类型而不是字符串。 And for the sake of best solutions instead of creation new classes try to use those that has been created FiledInfo instead of creation new.
并且为了最好的解决方案而不是创建新类,尝试使用那些已经创建的FiledInfo而不是创建新类。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.