模块加载时如何执行一次?

Posted

技术标签:

【中文标题】模块加载时如何执行一次?【英文标题】:How to execute once when module loads? 【发布时间】:2016-04-15 17:59:20 【问题描述】:

我需要从脚本中读取的字符串名称创建对象。我不想使用 Objective-C 运行时。

在我的 C++ 实现中,每个类都通过全局静态变量向对象工厂单例注册自己。当 dll 加载时,全局变量被初始化,所有可用的类都被注册。

我不希望对象工厂具有所有可能类型的硬编码预知识。

在 Swift 中,所有全局变量都是延迟初始化的,因此我的 C++ 注册策略不起作用。

是否有一些初始化 API 可以在每个模块加载时快速调用一次? 如果没有,有没有人知道课程注册的好主意?

public enum DynamicTypeFactoryError : ErrorType 
    case ClassNotRegistered


public protocol DynamicType 
    static var dynamicClassName: String  get 
    init()


public struct DynamicTypeRegistraion<T: DynamicType> 
    public init() 
        DynamicTypeFactory.inst.register(T.dynamicClassName, factory:  T() )
    


//===========================================================================
// singleton
public class DynamicTypeFactory 
    // properties
    public static let inst = DynamicTypeFactory()
    typealias ClassFactoryType = (Void) -> DynamicType
    var registry = [String : ClassFactoryType]()

    // methods
    public func create(className: String) throws -> DynamicType 
        // make sure the class exists
        guard let factory = registry[className] else 
            throw DynamicTypeFactoryError.ClassNotRegistered
        
        return factory()
    

    /// This is used to register an object so it can be dynamically created
    /// from a string.
    public func register(className: String, factory: (Void) -> DynamicType) 
        if (registry[className]) != nil 
            // TODO - this should be logged
            assertionFailure("Class: \(className) is already registered")
         else 
            registry[className] = factory
        
    


//===========================================================================
// MyObject
public struct MyObject : DynamicType 
    // properties
    static let registration = DynamicTypeRegistraion<MyObject>()
    public static var dynamicClassName = "MyObject"
    public init() 
    


// Usage
let myObj = try? DynamicTypeFactory.inst.create("MyObject")

由于MyObject的静态注册没有初始化,调用create失败,因为它还没有注册。

【问题讨论】:

Swift 中没有(据我所知)这样的机制。例如,参见***.com/questions/28422468/… 或***.com/questions/24898453/… 中的讨论。 您能否举例说明您正在做什么以及为什么延迟初始化不适用于您的情况?也许有一个变通办法,通过一个例子就会变得很明显。 【参考方案1】:

查看 Martin R 发布的链接后,似乎没有“非惰性”静态初始化,这是设计使然。因此,Swift 应用程序需要一种不同的方法。谢谢马丁!

【讨论】:

【参考方案2】:

Objective C 中有两种方法用于加载和初始化一个类。 +load 和 +initialize 1. 在swift中你可以使用“public override class func initialize()”来放置你的初始化代码,请注意它会被懒惰地调用。

    在 Swift 1.2 中删除了对覆盖负载的支持

这是关于初始化方法的文档所说的

“运行时向程序中的每个类发送初始化,就在类或任何继承自它的类从程序中发送其第一条消息之前。运行时将初始化消息发送到线程安全中的类方式。超类在其子类之前收到此消息。”

【讨论】:

以上是关于模块加载时如何执行一次?的主要内容,如果未能解决你的问题,请参考以下文章

liteos动态加载(十三)

模块的导入方法

python如何重新加载模块

Perl6 如何决定加载哪个版本的模块?

在java中如何保证程序模块只被执行一次

LMOD TCL 在加载模块时执行 bash 脚本