【问题标题】:Castle DynamicProxy generated class namesCastle DynamicProxy 生成的类名
【发布时间】:2010-11-19 04:09:39
【问题描述】:

有人知道是否可以控制通过 Castle DynamicProxy 生成的类型的名称吗?我希望利用持久化 Castle 生成的程序集的能力,为我的项目添加一些具有某些特定功能的附加类,但我希望能够控制这些生成的代理类型的名称。任何帮助将不胜感激。

我实际上计划保留这些类的实例以及作为 NHibernate 代理源的原始类的实例。因此,我需要这些名称在多代程序集中保持一致。

【问题讨论】:

    标签: nhibernate castle-dynamicproxy


    【解决方案1】:

    我做了一些有趣的挖掘工作。使用 INamingScope 指定代理名称似乎是可能的,但是将 INamingScope 嵌入其中远非简单。您需要创建自己的 ProxyFactoryFactory,这将创建一个与 NHibernate.ByteCode.Castle.ProxyFactory 相同的 ProxyFactory,除了它将初始化 ProxyGenerator:

    public class CustomProxyFactory : AbstractProxyFactory {
        private static readonly ProxyGenerator ProxyGenerator = new ProxyGenerator(new CustomProxyBuilder());
        // remainder of code is identical
    }
    
    public class CustomProxyBuilder : DefaultProxyBuilder {
        public CustomProxyBuilder() : base(new CustomModuleScope()) {}
    }
    
    public class CustomModuleScope : ModuleScope {
        public CustomModuleScope() : base(false, false, new CustomNamingScope(), DEFAULT_ASSEMBLY_NAME, DEFAULT_FILE_NAME, DEFAULT_ASSEMBLY_NAME, DEFAULT_FILE_NAME) {}
    }
    
    public class CustomNamingScope : INamingScope {
        public CustomNamingScope() {}
    
        private CustomNamingScope(INamingScope parent) {
            ParentScope = parent;
        }
    
        public string GetUniqueName(string suggestedName) {
            // your naming logic goes here
        }
    
        public INamingScope SafeSubScope() {
            return new CustomModuleScope(this);
        }
    
        public INamingScope ParentScope { get; private set; }
    }
    

    老实说,我没有尝试过运行或编译任何这些。只是挖掘 NHibernate 和 Castle.Core 源代码。希望它能给你一些想法......

    【讨论】:

    • 我会在接下来的几天里试一试,然后告诉你进展如何。
    • 鬼鬼祟祟,很鬼鬼祟祟;)您正确地指出这远非简单,这是有原因的。它并不完全是要被覆盖的。无论如何,如果你这样做,有一个假设(不记得是否记录)命名范围将是一致的 - 对于给定的suggestedName,它将总是返回相同的唯一名称(显然它必须是再次唯一,如果您调用该方法两次,它应该始终返回相同的第二个值,依此类推)。反序列化过程取决于它。
    • 嗨 Krysztof,当代理给定类时,DynamicProxy 中的 INamingScope 的默认实现是否总是生成相同的类名,即使在应用程序的后续运行中,还是会在应用程序域生成一个新名称已卸载并再次加载?另外,如果被代理的类在运行之间被修改了怎么办?
    • 只将姓名和订单记入账户。最好运行编写一个原型并尝试做任何你需要的事情,看看它是否适用于你的场景
    • 我不断收到System.ArgumentException: Duplicate type name within an assembly.,除非我返回一个随机生成的名称,这与文档背道而驰:“实施者必须返回确定性名称,即使用相同的建议名称调用两次GetUniqueName,每次都应提供相同的返回名称。不确定的返回值,如附加随机后缀会破坏代理的序列化。"
    【解决方案2】:

    看看 NHContrib 中的 ProxyGenerators 项目。它允许您预先生成 NHibernate 的延迟加载代理。

    http://nhforge.org/wikis/proxygenerators10/default.aspx

    无论您是否使用 ProxyGenerators,您都可以通过 Proxy Factory Factory 将您的自定义代理集成到 NHibernate。在 hibernate.cfg.xml 中:

    <hibernate-configuration xmlns="urn:nhibernate-configuration-2.2">
      <session-factory>
        <property name="proxyfactory.factory_class">YOUR_PROXY_FACTORY_FACTORY</property>
      </session-factory>
    </hibernate-configuration>
    

    【讨论】:

    • 我认为你误解了我的目标。我不想改变 NHibernate 代理的工作方式。我想要另一组从现有持久类派生的具有附加行为的持久类。因此,如果我有一个名为 Product 的类,我想生成一个名为 ProductOverride 的代理类,它派生自 Product,它会改变行为,但也会有稍微不同的数据库映射。所以,我的问题更多是关于 DynamicProxy 而不是关于 NHibernate。我意识到我可以通过一些代码生成来实现这一点,但我宁愿它发生在运行时。
    • 你为什么不使用标准的 NHibernate 继承映射来完成这个?为什么你还需要处理动态代理?
    • 因为我不想维护这些类。我不是在寻找替代设计。我有一些。手动创建实际类,通过代码生成创建实际类。它们都导致双倍的维护工作量。我希望避免这种情况。
    • 我很困惑。如果您不想维护这些类,您打算将代码放在哪里?您也许可以使用 AOP 来做到这一点,但我需要了解更多关于您的使用场景的信息。
    • 除了拦截器和生成类的代码之外,不会有任何代码。我完全了解 NHibernate 的功能,以及它如何使用 Castle DynamicProxy。我想要的与 AOP 类似,因为我想使用拦截,但我想将代理保留为第一类实体,以便它们可以重新水化并与它们所基于的类分开使用。那么,回到我最初的问题:你知道是否可以控制 Castle DynamicProxy 生成的代理的命名吗?如果不可能,那就不可能。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-31
    • 2017-02-12
    • 2011-04-26
    • 1970-01-01
    • 2012-06-20
    • 2016-11-30
    相关资源
    最近更新 更多