【问题标题】:How do I attach a method to a dynamically-created C# type at runtime?如何在运行时将方法附加到动态创建的 C# 类型?
【发布时间】:2010-10-17 03:32:52
【问题描述】:

我一直在使用一个内部数据访问库,该库实际上是将 XML 传递给一个存储过程,该存储过程返回 XML。我对此无能为力。我试图让 ActiveRecord 获得批准,但我的请求被拒绝了。但是,使用http://blog.bodurov.com/Post.aspx?postID=27 提供的出色代码,我向 IEnumerable 添加了一个扩展方法,该方法将我从杂乱无章的 XML 中创建的键值对转换为强类型对象,并带有属性名称!

这个:

dict["keyName1"]

变成

MyObject.keyName1

现在接口支持数据绑定!很酷!不过,我想更进一步。我希望发出的对象也具有 Save() 方法,这样我就可以模仿 ActiveRecord 模式,并为我的 web 人员提供一个直观的对象层,以便在 ASP.net 中使用。

如何在 Visual Studio 的源代码中编写方法,并在运行时将其附加到发出的对象?我对编写汇编或 IL 不感兴趣(或没有资格)。我想在 C# 中执行此操作。这是我的第一个 StackOverflow 问题,我使用公司规定的 IE6 发布此问题,所以请保持温和。

【问题讨论】:

    标签: c# reflection dynamic-languages


    【解决方案1】:

    我认为这被称为混入,在 .net 中无法直接或轻松使用。但是据我了解,这是设计LinFu 框架的主要原因之一。

    【讨论】:

      【解决方案2】:

      根据我从那篇文章中收集到的信息,它正在为您创建匿名类型,并且您正在使用它来获取值。如果是这种情况,就没有简单的方法可以向这些对象添加方法。但是,如果每次 SP 执行时 XML 结构都相同,为什么不创建一个具有您需要的所有属性的具体类,并使用 XML 自己填充这些对象的集合。这样,您可以轻松地将所需的任何方法直接添加到类中...

      编辑:根据我们在 cmets 中的讨论,这是一个想法:

      在那里的代码中,当您构建类型时,您使用的是:ModuleBuilder.DefineType。 DefineType 有一个重载,它需要一个类型来扩展。 Link.。因此,创建一个接口(事件中不必包含任何方法),当您动态构建类型时,使用我链接到的重载扩展该接口。然后在该接口上创建一个执行 Save() 的扩展方法。

      还有另一个可能感兴趣的重载需要扩展类型和接口:

      http://msdn.microsoft.com/en-us/library/f53tx4x8.aspx

      EDIT2:代码示例:

      首先,创建一个接口:

      public interface ISaveExtentable //I suck at naming stuff :-p
      {
      
      }
      

      然后,在您喜欢的那个站点的代码中,您会发现一个名为:GetTypeBuilder 的方法。改成这样:

              private static TypeBuilder GetTypeBuilder(string typeSigniture)
              {
                  AssemblyName an = new AssemblyName("TempAssembly" + typeSigniture);
                  AssemblyBuilder assemblyBuilder =
                      AppDomain.CurrentDomain.DefineDynamicAssembly(
                          an, AssemblyBuilderAccess.Run);
                  ModuleBuilder moduleBuilder = assemblyBuilder.DefineDynamicModule("MainModule");
      
                  TypeBuilder tb = moduleBuilder.DefineType("TempType" + typeSigniture
                                      , TypeAttributes.Public |
                                      TypeAttributes.Class |
                                      TypeAttributes.AutoClass |
                                      TypeAttributes.AnsiClass |
                                      TypeAttributes.BeforeFieldInit |
                                      TypeAttributes.AutoLayout
                                      , typeof(object), new Type[] {typeof(ISaveExtentable)});
                  return tb;
              }
      

      然后,在该接口上创建一个扩展方法来进行保存:

          public static class SaveExtendableExtensions
          {
                public static void Save(this ISaveExtentable ise)
                {
                    //implement save functionality. 
                }
          }
      

      您很可能需要在 Save 方法中使用反射来获取所有属性,因为该类型是动态创建的。

      【讨论】:

      • "如果每次 SP 执行时 XML 结构都相同" 我得到 BRD 1245 RFW 3456项目名称!etc 每次都有不同的属性 :(
      • 是的,但我确信有一个可供选择的属性列表。将所有这些属性作为 Nullable 字段(如果它们是值类型)放入类中,并仅填充您返回的那些。我认为您不需要使用一些疯狂的解决方案来动态构建类型...
      • XML 是动态生成的,我不想为每个排列维护一个具体类的库。
      • 我喜欢这个编辑。我不是想要求 da codez,但你介意在你的答案中抛出一些示例代码来更好地勾勒出这个想法吗?
      • 恐怕您在这种情况下使用 TypeBuilder 会引入内存泄漏。以这种方式生成的程序集不会从当前应用程序域中卸载,直到整个域被卸载(意味着应用程序关闭)。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-11
      • 2020-05-03
      • 2011-10-15
      • 1970-01-01
      • 2016-12-28
      • 1970-01-01
      相关资源
      最近更新 更多