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

发布于 2024-07-17 05:49:23 字数 694 浏览 5 评论 0原文

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

这:

dict["keyName1"]

变成

MyObject.keyName1

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

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

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

走野 2024-07-24 05:49:23

根据我在那篇文章中收集的信息,它正在为您创建匿名类型,并且您使用它来获取值。 如果是这样的话,就没有简单的方法可以向这些对象添加方法。 但是,如果每次 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
{

}

然后,在您喜欢的该站点的代码中,您会发现一个名为: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 方法中使用反射来获取所有属性,因为该类型是动态创建的。

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.

夜巴黎 2024-07-24 05:49:23

我认为这称为混合,在 .net 中不能直接或轻松获得。 然而,据我了解,这是 LinFu 框架被淘汰的主要原因之一设计的。

I think this is called mix-ins which aren't directly or easily available in .net. However as I understand it this is one of the main reasons the LinFu framework was designed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文