Как динамически создать класс в C#?
У меня есть класс, который выглядит так:
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 находился в моей файловой системе.
16 ответов
Да, вы можете использовать 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
(CompileAssemblyFromSource) - Найти сгенерированный тип
- И создать экземпляр этого типа (
Activator.CreateInstance
)
Таким образом, вы можете работать с уже известным вам кодом C#, вместо того, чтобы создавать MSIL.
Но это работает лучше всего, если ваш класс реализует некоторый интерфейс (или является производным от некоторого базового класса), иначе как вызывающий код (читай: компилятор) узнает об этом классе, который будет сгенерирован во время выполнения?
Вы также можете динамически создать класс с помощью 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# 6.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" };
Спросите Ганса, вы можете использовать Roslyn для динамического создания классов.
Полный источник:
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:
... Этот граф объектов может быть представлен как исходный код с использованием генератора кода CodeDOM для поддерживаемого языка программирования. CodeDOM также можно использовать для компиляции исходного кода в двоичную сборку.
Вы также можете динамически создавать класс с помощью DynamicExpressions.
Так как "Словарь" имеет компактные инициализаторы и обрабатывает столкновения клавиш, вы захотите сделать что-то подобное.
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);
}
Для тех, кто хочет создать динамический класс просто свойств (например, 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;
}
}
}
}
Основываясь на ответе @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
Вы можете посмотреть на использование динамических модулей и классов, которые могут выполнять эту работу. Единственным недостатком является то, что он остается загруженным в домене приложения. Но с использованием версии.NET Framework это может измениться. .NET 4.0 поддерживает коллекционные динамические сборки и, следовательно, вы можете динамически воссоздавать классы / типы.
Вот Это Да! Спасибо за этот ответ! Я добавил некоторые функции для создания конвертера datatable 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
И в подпункте "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
Вы можете использовать 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
Я вижу здесь 3 вопроса:
1. Я хочу создать класс, который выглядит следующим образом: Есть ли способ это сделать?
class DynamicClass
{
int EmployeeID,
String EmployeeName,
String Designation
}
Да, это возможно, но цель должна состоять не в том, чтобы класс выглядел как-то, а в том, чтобы он работал, вел себя и хранил данные таким образом. И это достижимо с использованиемCodeGeneration
, "T4 Template
,dynamic
,ExpandoObject
,CSharpProvider
илиAnonymousObject
.
2. Я хочу, чтобы это создавалось во время выполнения.
Генерация во время выполнения ничего не даст, если она не создастinstance
объект.
И насколько я понимаю, вы пытаетесь сохранить данные размеромList<Field>
является несвязанным, и лучшее, что вы можете придумать, — это создать объект для динамического хранения этих неограниченных данных во время выполнения.
Создание динамической сущности
Если это ваша проблема, вы можете попытаться создатьEmployee
какEntity
как показано ниже, называется какDynamicEntity
где недвижимость доступна в виде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
Если все пойдет хорошо, вы можете получить такой объект:
Вы можете использовать System.Runtime.Remoting.Proxies.RealProxy. Это позволит вам использовать "нормальный" код, а не низкоуровневый тип ассемблера.
Посмотрите ответ RealProxy на этот вопрос для хорошего примера:
Runtime Code Generation with JVM and CLR
- Питер Сестофт
Работа для людей, которые действительно заинтересованы в этом типе программирования.
Мой совет для вас: если вы объявляете что-то, старайтесь избегать строки, поэтому, если у вас есть класс Field, лучше использовать класс System.Type для хранения типа поля, а не строки. И ради лучших решений вместо создания новых классов попробуйте использовать те, что были созданы FiledInfo вместо создания новых.