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

Chr*_*all 7 c# reflection dynamic-languages

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

这个:

dict["keyName1"]
Run Code Online (Sandbox Code Playgroud)

MyObject.keyName1
Run Code Online (Sandbox Code Playgroud)

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

如何在Visual Studio中编写方法,在源代码中,并在运行时将其附加到发出的对象?我对编写程序集或IL不感兴趣(或有资格).我想在C#中这样做.这是我的第一个StackOverflow问题,我发布的是公司授权的IE6,所以请保持温和.

BFr*_*ree 2

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

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

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

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

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

编辑2:代码示例:

首先,创建一个接口:

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

}
Run Code Online (Sandbox Code Playgroud)

然后,在该站点中您喜欢的代码中,您将找到一个名为: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;
        }
Run Code Online (Sandbox Code Playgroud)

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

    public static class SaveExtendableExtensions
    {
          public static void Save(this ISaveExtentable ise)
          {
              //implement save functionality. 
          }
    }
Run Code Online (Sandbox Code Playgroud)

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