클래스를 동적으로 생성하는 방법은 무엇입니까?
다음과 같은 수업이 있습니다.
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 파일이 내 파일 시스템에 있는 것을 원하지 않습니다.
예, 사용할 수 있습니다.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);
}
}
}
그것은 약간의 노력이 필요하겠지만, 확실히 불가능한 것은 아닙니다.
제가 한 일은 다음과 같습니다.
- 문자열에 C# 소스를 생성합니다(파일에 쓸 필요 없음).
- 에서 합니다.
Microsoft.CSharp.CSharpCodeProvider
를 원본에서 컴파일소스에서컴일 - 생성된 유형 찾기
- 그)를 .
Activator.CreateInstance
)
이렇게 하면 MSIL을 방출하는 대신 이미 알고 있는 C# 코드를 처리할 수 있습니다.
그러나 클래스가 어떤 인터페이스(또는 어떤 기본 클래스에서 파생됨)를 구현하는 경우에는 이것이 가장 잘 작동합니다. 그렇지 않으면 호출 코드(읽기: 컴파일러)가 런타임에 생성될 클래스에 대해 어떻게 알 수 있습니까?
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;
}
이 오래된 작업을 다시 시작하는 것은 알지만 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 를 참조하십시오.
저는 이러한 동적 클래스의 의도된 사용법을 잘 모르고 코드 생성과 런타임 컴파일은 할 수 있지만 약간의 노력이 필요합니다.Anonymous Types가 다음과 같은 도움이 될 수 있습니다.
var v = new { EmployeeID = 108, EmployeeName = "John Doe" };
Hans가 제안한 대로 Roslin을 사용하여 동적으로 클래스를 만들 수 있습니다.
전체 소스:
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;
}
}
}
당신은 CodeDOM을 보고 싶어합니다.코드 요소를 정의하고 컴파일할 수 있습니다.MSDN 인용:
...이 개체 그래프는 코드를 사용하여 소스 코드로 렌더링할 수 있습니다.지원되는 프로그래밍 언어에 대한 DOM 코드 생성기입니다.코드DOM은 소스 코드를 이진 어셈블리로 컴파일하는 데도 사용할 수 있습니다.
동적 표현식을 사용하여 클래스를 동적으로 만들 수도 있습니다.
'Dictionary'에는 콤팩트 이니셜라이저가 있고 키 충돌을 처리하기 때문에 이런 작업이 필요합니다.
var list = new Dictionary<string, string> {
{
"EmployeeID",
"int"
}, {
"EmployeeName",
"String"
}, {
"Birthday",
"DateTime"
}
};
또는 JSON 변환기를 사용하여 직렬화된 문자열 개체를 관리 가능한 개체로 구성할 수도 있습니다.
그런 다음 시스템을 사용합니다.Linkq.Dynamic;
IEnumerable<DynamicProperty> props = list.Select(property => new DynamicProperty(property.Key, Type.GetType(property.Value))).ToList();
Type t = DynamicExpression.CreateClass(props);
나머지는 그냥 시스템을 사용하는 것입니다.반사.
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);
}
@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
동적 클래스를 만들려는 사용자는 속성(예: 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를 참조해야 합니다.코드 분석.CSSharp 라이브러리.
/// <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;
}
}
}
}
작업을 수행할 수 있는 동적 모듈 및 클래스를 사용할 수 있습니다.유일한 단점은 앱 도메인에 로드된 상태로 남아 있다는 것입니다.하지만 의 버전으로.사용 중인 NET 프레임워크는 변경될 수 있습니다.NET 4.0은 수집 가능한 동적 어셈블리를 지원하므로 클래스/유형을 동적으로 재생성할 수 있습니다.
와! 답변 감사합니다!저는 당신과 공유하는 "데이터 테이블 to 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
그리고 "compile result type" 하위 항목에서 다음과 같이 변경했습니다.
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
CSSharpProvider를 사용할 수 있습니다.
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
시스템을 사용할 수 있습니다.런타임.원격.대리인.진짜 프록시.그것은 당신이 낮은 수준의 어셈블리 유형의 것이 아닌 "일반적인" 코드를 사용할 수 있게 해줄 것입니다.
좋은 예는 이 질문에 대한 RealProxy 답변을 참조하십시오.
C#에서 메서드 호출을 가로채려면 어떻게 해야 합니까?
여기에 세 가지 질문이 있습니다.
다음과 같은 클래스를 만들고 싶습니다.이것을 할 수 있는 방법이 있습니까?
class DynamicClass
{
int EmployeeID,
String EmployeeName,
String Designation
}
예, 이것은 가능하지만 그 목적은 클래스를 어떤 것처럼 보이게 하는 것이 아니라 이렇게 일하고, 행동하고, 데이터를 유지하는 것이어야 합니다.그리고 이것은 다음을 사용하여 화이트아웃할 수 있습니다.CodeGeneration
, "T4 Template
,dynamic
,ExpandoObject
,CSharpProvider
또는AnonymousObject
.
나는 이것이 런타임에 생성되기를 원합니다.
class
런타임에 생성되지 않으면 아무것도 하지 않습니다.instance
물건.
그리고 만약 내가 이해한다면, 당신은 당신을 구하려고 노력하고 있습니다.Employee
크 가 있 데 이 터 는 기의 List<Field>
언바운드되고 당신이 생각할 수 있는 최선의 방법은 생성하는 것입니다.class
제한되지 않은 데이터를 런타임에 동적으로 유지합니다.
동적 도면요소 작성
문제가 발생한 경우 생성을 시도할 수 있습니다.Employee
로서Entity
하기와 같이DynamicEntity
속성을 a로 사용할 수 있는 경우Dictionary<string,object>
따라서 새로운 속성/필드를 사용하지 않고 확장할 필요가 없습니다.class
디자인은 직원들을 위한 2-3개의 분야에 국한되지 않습니다.
public class DynamicEntity
{
public string Name {get;private set;}
public Dictionary<string,object> Attributes;
public DynamicEntity(string name)
{
Name = name;
Attributes = new Dictionary<string,object>();
Attributes.Add("LogicalName",name);
Attributes.Add("Id",Guid.NewGuid());
}
public object this[string key]
{
get {
return Attributes[key];
}
set{
Attributes[key] = value;
}
}
public void AddAttribute<T>(string attributeName,T data)
{
Attributes.Add(attributeName,data);
}
public void SetAttributeValue<T>(string attributeName,T data)
{
Attributes[attributeName] = data;
}
public T GetAttributeValue<T>(string attributeName)
{
return (T)Attributes[attributeName];
}
}
사용하기 위해 런타임에 개체를 만들고 속성을 읽고/쓰기/추가할 수 있습니다.
var u = new DynamicEntity("employee"); //new object
u.AddAttribute<int>("EmployeeID",10); //Add Id
u["EmployeeName"]= "vinod"; //Add Name
u["Designation"] = "hacker"; //Add Designation
u.AddAttribute<string>("Address","India"); //Add New Attribute
u.SetAttributeValue<string>("EmployeeName","Vinod Srivastav");
var id = u.GetAttributeValue<int>("EmployeeID"); //Read Attribute
모든 것이 잘되면 다음과 같은 개체를 얻을 수 있습니다.
Runtime Code Generation with JVM and CLR
피터 세스토프트
이런 종류의 프로그래밍에 정말 관심이 있는 사람들을 위해 일합니다.
당신을 위한 제 팁은 만약 당신이 무언가를 선언한다면 문자열을 피하려고 노력하는 것입니다, 그래서 만약 당신이 클래스 필드가 있다면 클래스 시스템을 사용하는 것이 더 낫습니다.문자열보다 필드 유형을 저장할 유형입니다.그리고 새로운 클래스를 만드는 대신 최상의 솔루션을 위해 새로운 클래스를 만드는 대신 FileInfo로 만든 클래스를 사용하려고 합니다.
언급URL : https://stackoverflow.com/questions/3862226/how-to-dynamically-create-a-class
'programing' 카테고리의 다른 글
HTTPWebrequest(다중 부품/폼 데이터)로 파일 업로드 (0) | 2023.05.02 |
---|---|
Angular2 변경 감지: ngOnChanges가 중첩된 개체에 대해 실행되지 않습니다. (0) | 2023.05.02 |
subprocess.run()의 출력을 억제하거나 캡처하는 방법은 무엇입니까? (0) | 2023.05.02 |
xcodeproject/project.pbxproj 파일을 무시해야 합니까? (0) | 2023.05.02 |
.NET에 아이콘 컬렉션이 있습니까? (0) | 2023.05.02 |