C# Emit ,如何编写 if 语句

2023-12-19

首先,我有课

    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;
    }

Updated

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 方法中调用它。


update 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;
}

update 3 screen-snaps enter image description here


update 4

enter image description here maybe , i have found the error reason , see Reflection Emit and Type Inheritance: Calling Base Type Constructors https://softwareproduction.eu/2014/07/21/reflection-emit-and-type-inheritance-calling-base-type-constructors/

update 5

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

C# 发出,类型值比较 https://stackoverflow.com/questions/54686465/c-sharp-emit-type-value-compare/54687187#54687187


@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;
            }
        }
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C# Emit ,如何编写 if 语句 的相关文章

  • 与 MinGW 的静态和动态/共享链接

    我想从一个简单的链接用法开始来解释我的问题 假设有一个图书馆z它可以编译为共享库 libz dll D libs z shared libz dll 或静态库 libz a D libs z static libz a 让我想要链接它 然后
  • copy_from_user() 错误:目标大小太小

    我正在为内核模块编写 ioctl 处理程序 我想从用户空间复制数据 当我编译禁用优化的代码时 O0 gflags 编译器返回以下错误 include linux thread info h 136 17 error call to bad
  • 使用管道在父级和子级之间传递整数值

    我对如何正确使用 pipeline 在两个进程之间传递整数值有点困惑 在我的程序中 我首先创建一个管道 然后分叉它 我假设我有 两个 管道 据我了解 这是我的任务 我的父母通过 for 循环检查某个操作的整数值 i 增加计数变量 并将值保存
  • 如何以编程方式删除受信任的根证书颁发机构中的证书?

    我需要能够从组织中的每台电脑中删除特定的证书 是的 我可以逐个座位 但我要到周四才能完成 而且我没有人力逐个座位 是否有使用 C 的编程方式来执行此操作 我认为你不需要编写任何 C 看看certmgr exe del http msdn m
  • 用于 C++ 中图像分析的 OpenCV 二进制图像掩模

    我正在尝试分析一些图像 这些图像的外部周围有很多噪声 但内部有一个清晰的圆形中心 中心是我感兴趣的部分 但外部噪声正在影响我对图像的二进制阈值处理 为了忽略噪音 我尝试设置一个已知中心位置和半径的圆形蒙版 从而使该圆之外的所有像素都更改为黑
  • 重载算术运算符

    赋值运算符可以声明为 T 运算符 const t 在类中 但不能以这种方式定义算术运算符 它必须是友元函数 我不明白为什么 你能解释一下吗 算术运算符不必须是友元 那么你可以这样定义 MyClass MyClass operator con
  • 从图像创建半透明光标

    是否可以从图像创建光标并使其半透明 我目前正在拍摄自定义图像并覆盖鼠标光标图像 如果我可以将其设为半透明 那就太好了 但不是必需的 销售人员喜欢闪亮的 目前正在做这样的事情 Image cursorImage customImage Get
  • 为什么连续抛出 2 个异常不会生成无法访问的代码警告?

    为什么以下代码行不会创建编译器警告 void Main throw new Exception throw new Exception 据我所知 编译器应该通知您无法到达第二个抛出异常 这显然是一个编译器错误 它是在 C 3 0 中引入的
  • main.cpp 是必需的吗?

    我试图编译一个程序cmake 我最终删除了我的main cpp文件 我刚刚将其复合到另一个包含我的项目名称的文件中 即 我刚刚将主函数剪切并粘贴到该文件中 问题是我有一个main cpp未发现错误 不确定是否在C 一个名为main cpp是
  • 将 AutomationID 与 ListView 结合使用

    我正在尝试将 AutomationId 附加到列表视图中的项目 理想情况下 将项目名称绑定到显示的项目
  • Clang 5.0 上的 vsprintf 和 vsnprintf [-Wformat-nonliteral] 警告

    我有这段代码 static void err doit int errnoflag int level const char fmt va list ap int errno save unsigned long n char buf MA
  • 具有多个父项的 Qt 树模型

    我想构建一棵树 其中一个元素可以引用另一个元素 我想要构建的树是 像这样的东西 A B C D E F P this is a pointer to C D first child of C E second child of C I fo
  • g++ / gcc 是否支持 C++20 新的atomic_flag 功能?

    根据参考参数 https en cppreference com w cpp atomic atomic flag c 20 有丰富的 对我来说有用的 支持atomic flag运营 然而 目前尚不清楚 gcc 是否支持这些功能 它们在任何
  • 使用未命名命名空间而不是静态命名空间

    我可以假设在未命名命名空间中声明的对象相当于static namespace int x 1 static int x 2 FWIK 在这两种情况下 x将具有静态存储期限和内部链接 声明为的对象的所有规则也是如此static适用于未命名名称
  • 让 Windows 尝试读取文件

    我正在对 Windows 文件系统进行某种封装 当用户请求打开文件时 Windows 调用我的驱动程序来提供数据 在正常操作中 驱动程序返回缓存的文件内容 但是 在某些情况下 实际文件没有缓存 我需要从网络下载它 问题是是否有可能让 Win
  • 为什么我可以在另一个函数中定义一个函数?

    请参阅下面的代码 我在另一个函数中定义了一个函数 void test1 void void test2 void printf test2 n printf test1 n int main void test1 return 0 这个用法
  • 异步/等待 - 是*并发*吗?

    我一直在考虑 C 5 中新的异步内容 并且出现了一个特殊问题 据我了解 await关键字是一个简洁的编译器技巧 语法糖来实现连续传递 http en wikipedia org wiki Continuation passing style
  • 跟踪白色背景中的白球(Python/OpenCV)

    我在 Python 3 中使用 OpenCV 来检测白场上的白 黑球 并给出它的精确 x y 半径 和颜色 我使用函数 cv2 Canny 和 cv2 findContours 来找到它 但问题是 cv2 Canny 并不总是检测到圆的完整
  • 尝试后终于没有被调用

    由于某种原因 在我的控制台应用程序中 我无法运行我的finally 块 我编写这段代码是为了测试finally块是如何工作的 所以它非常简单 static void Main int i 0 try int j 1 i Generate a
  • 使用通用存储库模式和流畅的 nHibernate

    我目前正在开发一个中型应用程序 它将访问不同站点上的 2 个或更多 SQL 数据库等 我正在考虑使用类似的东西 http mikehadlow blogspot com 2008 03 using irepository pattern w

随机推荐