如何在运行时将方法附加到动态创建的C#类型? [英] How do I attach a method to a dynamically-created C# type at runtime?

查看:138
本文介绍了如何在运行时将方法附加到动态创建的C#类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

此:

dict["keyName1"]

成为

MyObject.keyName1

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

如何在Visual Studio中以源代码编写方法,并在运行时将其附加到发出的对象?我对编写汇编或IL不感兴趣(或没有资格).我想用C#做到这一点.这是我的第一个StackOverflow问题,我将其与公司要求的IE6一起发布,请保持温柔.

解决方案

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

基于我们在评论中的讨论,这是一个想法:

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

可能还需要考虑另一个重载,该重载需要扩展类型并与接口进行连接:

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

代码示例:

首先,创建一个接口:

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方法中使用反射来获取所有属性.

I have been saddled with using an in-house data access library that is effectively XML passed to a stored procedure, which returns XML. There is nothing I can do about this. I tried to get ActiveRecord approved, but my request was declined. However, using the excellent code provided at http://blog.bodurov.com/Post.aspx?postID=27, I added an extension method to IEnumerable that converts the key-value pairs I make out of the ragged XML coming back into strongly typed objects, complete with property names!

This:

dict["keyName1"]

becomes

MyObject.keyName1

Now the interface supports databinding! Pretty cool! I'd like to take it a step further, though. I want the objects emitted to have Save() methods too, so that I can ape the ActiveRecord pattern and provide my web guys with an intuitive object layer to use from ASP.net.

How do I write a method in Visual Studio, in source code, and attach it at runtime to the emitted objects? I am not interested in (or qualified for) writing assembly or IL. I'd like to do this in C#. This is my first StackOverflow question and I am posting this with company-mandated IE6, so please be gentle.

解决方案

From what I gather on that article, it's creating anonymous types for you, and you're using that to get the values. If that's the case, there's no easy way to add methods on to those objects. However, if the XML structure will be the same every time the SP executes, why not create a concrete class that has all the properties you need, and populate a collection of those objects yourself with the XML. That way, you can easily add any methods you need directly into the class...

EDIT: Based on our discussion in the comments, here's a thought:

In the code there, when you're building up the type, you're using: ModuleBuilder.DefineType. There's an overload to DefineType which takes a type to extend. Link.. Therefore, create an interface (it doesn't event have to have any methods in it), and when you're dynamically building up the type, extend that interface using the overload I linked you to. Then create an extension method on that interface that does the Save().

There's another overload that may be of interest that takes a type to extend, and interfaces:

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

EDIT2: Code sample:

First, create an interface:

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

}

Then, in the code you liked to in that site, you'll find a method called: GetTypeBuilder. Change it to this:

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

Then, create an extension method on that interface to do the save:

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

You'll most likely need to use reflection in your Save method to get all the properties since the type was created dynamically.

这篇关于如何在运行时将方法附加到动态创建的C#类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆