gpt4 book ai didi

C# Emit ,如何编写 if 语句

转载 作者:行者123 更新时间:2023-11-30 15:14:28 25 4
gpt4 key购买 nike

首先,我有一个类

    internal class Parent
{
protected void Write(string message, [CallerMemberName] string caller = null)
{
Console.WriteLine($"{caller} :: {message}");
}
}

我想动态创建一个类,该类有一个属性“Name”,如果属性值改变然后调用 write 方法,看起来像

    class Child : Parent
{
private string _name;

public string Name
{
get { return _name; }
set
{
                if (_name != value)
{
Write("changedto: " + value);
_name = value;
}
            }
}
}

我想知道的是高亮条款。如何在 emit 中写入它。请帮忙。


我想要下面的一些代码

     private static MethodBuilder BuildSetter(TypeBuilder typeBuilder, PropertyInfo property, FieldBuilder fieldBuilder, MethodAttributes attributes)
{
var setterBuilder = typeBuilder.DefineMethod($"set_{property.Name}", attributes, null, new Type[] { property.PropertyType });
var ilGenerator = setterBuilder.GetILGenerator();

ilGenerator.Emit(OpCodes.Ldarg_0); //this
ilGenerator.Emit(OpCodes.Ldarg_1); // the first one in arguments list

//code should be here

ilGenerator.Emit(OpCodes.Stfld, fieldBuilder);
ilGenerator.Emit(OpCodes.Ret);

return setterBuilder;
}

已更新

var typeBuilder = moduleBuilder.DefineType(typeName, TypeAttributes.Public,typeof(PropertyChanged));


var t = typeof(PropertyChanged);

var m2 = t.GetMethod("ValueChanged");

你看,当我创建类型时,我使用父类型,在父类型中有一个名为“ValueChanged”的方法

protected void ValueChanged(object value,[CallerMemberName] string property = null)

我想在 set 方法中调用它。


更新 2

private static MethodBuilder BuildSetter(TypeBuilder typeBuilder, PropertyInfo property, FieldBuilder fieldBuilder, MethodAttributes attributes)
{
var propertyType = property.PropertyType;
var setterBuilder = typeBuilder.DefineMethod($"set_{property.Name}", attributes, null, new Type[] { propertyType });

var setIl = setterBuilder.GetILGenerator();
Label exitSet = setIl.DefineLabel(); // define label to jump in case condition is false
setIl.Emit(OpCodes.Ldarg_0); // this
setIl.Emit(OpCodes.Ldfld, fieldBuilder); // _name field
setIl.Emit(OpCodes.Ldarg_1); // value

var inequality = propertyType.GetMethod("Equals", new[] { propertyType});
setIl.Emit(OpCodes.Callvirt, inequality); // '!=' method
setIl.Emit(OpCodes.Brtrue_S, exitSet); // check for inequality


setIl.Emit(OpCodes.Ldarg_0); // load string literal
setIl.Emit(OpCodes.Ldarg_1); // value
setIl.Emit(OpCodes.Ldstr, property.Name);

var m = typeBuilder.BaseType.GetMethod("ValueChanged", new Type[] {typeof(object),typeof(string) });

setIl.Emit(OpCodes.Call, m);

setIl.Emit(OpCodes.Ldarg_0); // this
setIl.Emit(OpCodes.Ldarg_1); // value
setIl.Emit(OpCodes.Stfld, fieldBuilder); // save the new value into _name
setIl.MarkLabel(exitSet); // mark the label
setIl.Emit(OpCodes.Ret); // return

return setterBuilder;
}

更新 3屏幕快照 enter image description here

enter image description here


更新 4

enter image description here也许,我找到了错误原因,请参阅Reflection Emit and Type Inheritance: Calling Base Type Constructors

更新 5

最后,我得到了错误原因。这不是我在更新 4 时猜到的,它是由调用父方法“ValueChanged”引起的。在我们将参数传递给方法之前,如果原始数据类型是 IsValueType,我们应该将其Box 为 Object。请参阅下面的引用,

C# emit , type value compare

最佳答案

@AlbertK 的回答向您展示了正确的方法,我将添加完整的代码。希望对您有所帮助。

我把所有东西都放在一个方法中..按照你的意愿重构它。

// define assembly and module
var propertyName = "Name";
var propertyType = typeof(string);
var ab = AssemblyBuilder.DefineDynamicAssembly(
new AssemblyName("dynamicAssembly"),
AssemblyBuilderAccess.Save);
var mb = ab.DefineDynamicModule("dynamicModule", "dynamicModule.dll");

// define type, field and property
var tb = mb.DefineType("dynamicType");
var fb = tb.DefineField("_name", propertyType, FieldAttributes.Private);
var pb = tb.DefineProperty(propertyName, PropertyAttributes.HasDefault, propertyType, Type.EmptyTypes);
var get = tb.DefineMethod("get_" + propertyName, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, propertyType, Type.EmptyTypes);
var set = tb.DefineMethod("set_" + propertyName, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, null, new[] { propertyType });

// write the IL for the get method
var getIl = get.GetILGenerator();
getIl.Emit(OpCodes.Ldarg_0); // this
getIl.Emit(OpCodes.Ldfld, fb); // _name field
getIl.Emit(OpCodes.Ret);

// write the IL for the set method
var setIl = set.GetILGenerator();
Label exitSet = setIl.DefineLabel(); // define label to jump in case condition is false
setIl.Emit(OpCodes.Ldarg_0); // this
setIl.Emit(OpCodes.Ldfld, fb); // _name field
setIl.Emit(OpCodes.Ldarg_1); // value
var inequality = propertyType.GetMethod("op_Inequality", new[] { propertyType, propertyType });
setIl.Emit(OpCodes.Call, inequality); // '!=' method
setIl.Emit(OpCodes.Brfalse_S, exitSet); // check for inequality
setIl.Emit(OpCodes.Ldstr, "changedto:"); // load string literal
setIl.Emit(OpCodes.Ldarg_1); // value
var concat = propertyType.GetMethod("Concat", new[] { propertyType, propertyType });
setIl.Emit(OpCodes.Call, concat); // concat two strings (literal + value)
var writeline = typeof(Console).GetMethod("WriteLine", new[] { propertyType });
setIl.Emit(OpCodes.Call, writeline); // write
setIl.Emit(OpCodes.Ldarg_0); // this
setIl.Emit(OpCodes.Ldarg_1); // value
setIl.Emit(OpCodes.Stfld, fb); // save the new value into _name
setIl.MarkLabel(exitSet); // mark the label
setIl.Emit(OpCodes.Ret); // return
pb.SetGetMethod(get);
pb.SetSetMethod(set);

tb.CreateType(); // complete the type
ab.Save("dynamicModule.dll"); // save the assembly to disk

结果

internal class dynamicType
{
private string _name;

public string Name
{
get
{
return this._name;
}
set
{
if (this._name != value)
{
Console.WriteLine("changedto:" + value);
this._name = value;
}
}
}
}

关于C# Emit ,如何编写 if 语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54646543/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com