寻找关于如何在实例构造函数中分配我在RT中动态创建的支持字段的属性的解决方案。签名与编译器生成的属性匹配为自动属性。基本上它们将等同于下面列出的代码。
使用.NET Core 2.0
问题:如何使用Emit在构造函数中分配支持字段?
例如:
public class MyClass {
public MyClass(int f1, string f2) {
_field1 = f1;
_field2 = f2;
}
private readonly int _field1;
private readonly string _field2;
public int Field1 { get; }
public string Field2 { get; }
}
private static void CreateConstructor(TypeBuilder typeBuilder, IReadOnlyList<dynamic> backingFields) {
var constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.Standard, new[] {typeof(KeyValuePair<string, string>), typeof(Dictionary<string, Type>)});
var ctorIL = constructorBuilder.GetILGenerator();
// Load the current instance ref in arg 0, along
// with the value of parameter "x" stored in arg X, into stfld.
for (var x = 0; x < backingFields.Count; x++) {
ctorIL.Emit(OpCodes.Ldarg_0);
ctorIL.Emit(OpCodes.Ldarg_S, x+1);
ctorIL.Emit(OpCodes.Stfld, backingFields[x]);
}
ctorIL.Emit(OpCodes.Ret);
}
public .cctor(KeyValuePair<string, string> kvp, Dictionary<string, Type> collection) {
_Name = kvp.Key;
_JSON = kvp.Value;
_PropertyInfo = collection;
}
迭代界面中定义的方法并创建新属性&amp;具有新类型的私有设置者的访问者。
public interface IComplexType {
string Name { get; set; }
string JSON { get; set; }
object PropertyInfo { get; set; }
}
答案 0 :(得分:1)
<强>解决!强>
需要更改构造函数参数以匹配迭代次数,因为Ldarg_1更难以作为KeyValuePair并分配其Key&amp;值分别。
通过消除KVP并提供附加参数,构造函数定义如下:
var constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.Standard, new[] {typeof(string), typeof(string), typeof(Dictionary<string, Type>)});
var ctorIl = constructorBuilder.GetILGenerator();
for (var x = 0; x < backingFields.Count; x++) {
ctorIl.Emit(OpCodes.Ldarg_0);
ctorIl.Emit(OpCodes.Ldarg_S, x + 1);
ctorIl.Emit(OpCodes.Stfld, backingFields[x]);
}
ctorIl.Emit(OpCodes.Ret);
要调用,我只是在这里提取了KVP的内容:
return (T) Activator.CreateInstance(TypeCollection[type], kvp.Key, kvp.Value, collection);