c# - 如何在运行时将方法附加到动态创建的 C# 类型?

标签 c# reflection dynamic-languages

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

这个:

dict["keyName1"]

成为

MyObject.keyName1

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

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

最佳答案

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

编辑:根据我们在评论中的讨论,这里有一个想法:

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

还有另一个可能感兴趣的重载,它需要一个类型来扩展和接口(interface):

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

EDIT2:代码示例:

首先,创建一个接口(interface):

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

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

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

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

关于c# - 如何在运行时将方法附加到动态创建的 C# 类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/710189/

相关文章:

c# - 为什么我会在字节数组的开头得到一个额外的字符(点或圆点)?

c# - 我想通过反射得到一个方法

python - 动态语言的用途

php - 数据库连接池真的那么重要吗?

Java,在开发过程中使用Groovy(Grails)只是为了能够测试代码而无需重新编译?

c# - 为什么我的 XAML 控件没有显示在代码隐藏中?

c# - C Server 和 C# Server 之间的通信仅发送 "p"字符

c# - 如何在 C# 中进行并发 API 调用?

class - 如何从隐式 ClassTag[T] 获取 Class[T]?

c# - 在进程中访问 "autos"(在运行时)