3

有一个事件AppDomain.CurrentDomain.DomainUnload允许清理独立于任何特定类实例甚至任何特定类的静态资源。我认为它是在我当前程序集中的任何代码之后执行的代码(顺便说一句,我是对的吗?)。

但是有没有办法编写一段代码(用于当前程序集),该代码要在当前程序集(类库)中的任何其他代码之前执行?或者我应该寻找一种更棘手的方法来在任何代码开始执行之前初始化一些资源?

我知道静态构造函数,但它们的调用顺序没有明确定义。换句话说,不能保证特定的静态构造函数将在其他类的其他静态构造函数之前执行。

还有一个AppDomain.AssemblyLoad。我不确定这是我要找的东西。此事件在加载 OTHER 程序集时发生,而不是当前程序集。

4

5 回答 5

2

我遇到了同样的问题并以这种方式解决了。我只用方法定义了一个IAssembyInitializer接口void Initialize()。在每个我想在加载后执行一些代码的程序集中,我定义了一个实现这个接口的类。我定义了一个属性来指定程序集中实现此接口的类(否则您可以通过反射找到它们,但我更喜欢这种方式):

[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
public class AssemblyInitializerAttribute : Attribute
{
    AssemblyInitializerAttribute ()
    {
    }
    AssemblyInitializerAttribute (string typeName)
    {
        TypeName = typeName;
    }
    public string TypeName;
}

属性在 AssemblyInfo 中以这种方式设置:

[assembly: AssemblyInitializerAttribute ("MyNamespace.AnAssemblyInitializer")]

最后,在应用程序的主程序集中,我向 AssemblyLoad 事件注册了一个执行所有初始化的方法:

AppDomain.CurrentDomain.AssemblyLoad += new AssemblyLoadEventHandler(NewAssemblyLoaded);

        static void NewAssemblyLoaded(object sender, AssemblyLoadEventArgs args)
        {
            Assembly anAssembly = args.LoadedAssembly;
            AssemblyInitializerAttribute[] initializers = (AssemblyInitializerAttribute[])anAssembly .GetCustomAttributes(typeof(AssemblyInitializerAttribute), false);
            foreach (AssemblyInitializerAttribute anInit in initializers)
            {
                Type initType = anInit.TypeName != null ? anAssembly.GetType(anInit.TypeName) : null;
                if (initType != null && initType.GetInterface("IAssemblyInitializer") != null)
                {
                    IAssemblyInitializer anInitializer = (IAssemblyInitializer)Activator.CreateInstance(initType);
                    anInitializer.Initialize();
                }
            }
        }
于 2013-01-24T13:46:33.913 回答
1

您可以使用静态字段中的实例Lazy<T>来自己控制静态初始化顺序。这些Lazy<T>初始化器对象的代码体可以引用Lazy<T>自动编排初始化 DAG 的其他实例。显然,你不能有周期。

使用 C++/CLI,您确实可以在程序集加载时执行代码(模块初始化程序)。你可能不想走那条路。

使用 C# 这是不可能的。静态 ctors 和惰性初始化模式是最好的。

于 2013-01-24T13:26:18.180 回答
0

您可能想扫描代码并找到那些需要完成初始化的地方。

然后在初始化尚未运行时在需要初始化之前启动初始化。

在 .NET 中,您根本不知道何时加载程序集,因此无法保证初始化将在所有情况下及时开始。

另一种方法是程序集的客户端通过调用方法显式启动初始化。(如果还没有加载,这也会加载程序集)

可以像在客户端中那样使用 AssemblyLoad 事件来检测特定程序集的加载,但这将使初始化依赖于客户端实现,而第一个解决方案将此责任保留在程序集本身的范围内。

于 2013-01-24T13:37:58.230 回答
0

假设您无法控制类库的使用方式,您可以为库中的每个公共/受保护类编写静态构造函数,并从每个类调用初始化代码。显然,初始化代码必须跟踪第一次调用(通过静态字段),以便它只运行一次。

于 2013-01-25T06:49:16.757 回答
-1

您可以使用Module Initializers来做到这一点。C# 不直接支持它们,但如果您不反对使用Cecil对程序集进行后处理,则可以使用它们。

于 2013-01-24T16:53:50.887 回答