当控制静态构造函数被调用 [英] Controlling when the Static Constructor is called

查看:139
本文介绍了当控制静态构造函数被调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的自定义属性的静态构造函数,我搜索装饰着我的所有属性的类加载的程序集并对其执行一些动作。

我想静态构造函数中运行时尽快调用$ P $的静态无效的主要()切入点执行之前pferably

目前我做一些调用属​​性之后只被调用。我的可能的其他地方做出这样的电话在我的程序,但理想属性的功能是独立的。

为了寻找答案,我rel=\"nofollow\"> MSDN <阅读本上


  

用户具有当静态构造在执行程序上的控制


但肯定有一些棘手的,狡猾的,或恶作剧的解决方法,以获取静态构造函数被称为ASAP项目。也许一个属性,反射,或一些其他类型的魔术可以使用。 能不能做到?

因为人们会肯定地告诉我,有没有很好的理由做什么,我问,我present我的目的,我的code:我试图使用属性来声明配置<一HREF =htt​​p://en.wikipedia.org/wiki/Db4o相对=nofollow> db4o的工厂。如果以后我已经建立了连接我的属性的静态构造函数被调用,那么就没有任何作用,是无用的。因此,我的计划都将有机会建立这样一个连接之前,必须调用。

  [AttributeUsage(AttributeTargets.Class,继承=假,的AllowMultiple = FALSE)]
密封公共类CascadeOnUpdateAttribute:属性
{
    公共BOOL标志{搞定;私人集; }    公共CascadeOnUpdateAttribute():这个(真){}    公共CascadeOnUpdateAttribute(布尔标志)
    {
        标志=标志;
    }    静态CascadeOnUpdateAttribute()
    {
        在AppDomain.CurrentDomain.GetAssemblies从装配VAR的目标=()
          从类型assembly.GetTypes()
          从type.GetCustomAttributes属性(typeof运算(CascadeOnUpdateAttribute),FALSE).Cast&LT; CascadeOnUpdateAttribute&GT;()
          选择新{type =类型,级联= attribute.Flag};        的foreach(在目标VAR目标)
        {
            。Db4oFactory.Configure()对象类(target.Type).CascadeOnUpdate(target.Cascade);
        }
    }
}

更新:

我最终使用一个静态方法的抽象属性。通过这种方式,因为我喜欢,我可以得到尽可能多的属性,它们都将通过调用这个方法适用于指定的配置。

 公共抽象类Db4oAttribute:属性
{
    公共抽象无效配置(IConfiguration配置,型号类型);    公共静态无效ApplyAttributes(IConfiguration配置)
    {
        在AppDomain.CurrentDomain.GetAssemblies从装配VAR的目标=()
          从类型assembly.GetTypes()
          从type.GetCustomAttributes属性(typeof运算(Db4oAttribute),FALSE).Cast&LT; D​​b4oAttribute&GT;()
          选择新{type =类型,属性=属性};        的foreach(在目标VAR目标)
        {
            target.Attribute.Configure(配置,target.Type);
        }
    }
}

和调用点:

  Db4oAttribute.ApplyAttributes(Db4oFactory.Configure());
_db = Db4oFactory.OpenFile(Test.db4o);


解决方案

正如马克说,我会做明确的如果我是你。

您的可以的显式使用的 Type.TypeInitializer 财产和调用它。然而,这将导致它再次运行的,即使它已经运行的可能产生意想不到的结果。

我个人动议code OUT的静态初始化完全。它的配置code - 为什么不只是让一个静态方法,你可以显式调用?我甚至不知道我有它的属性类本身,但至少明确呼吁:

  CascadeOnUpdateAttribute.ConfigureDb4oFactories();

比调用一个虚拟的方法或强制式初始化一些其他的方式更清晰,只是为了获得一个副作用。

In my custom attribute's static constructor, I search the loaded assembly for all classes decorated with my attribute and perform some action on them.

I would like the static constructor to be called as soon as possible during runtime, preferably before execution of the static void Main() entry point.

Currently it only gets called after I make some call to the attribute. I could make such a call elsewhere in my program, but ideally the attribute's functionality would be self-contained.

Looking for answers, I read this on MSDN:

The user has no control on when the static constructor is executed in the program.

But surely there is some tricky, sly, or mischievous workaround to get a static constructor to be called ASAP. Perhaps an attribute, reflection, or some other kind of magic could be used. Can it be done?

Because people would undoubtedly tell me that there is no good reason to do what I ask, I present my purpose and my code: I am trying to use attributes to declaratively configure a db4o factory. If my attribute's static constructor is called after I've already established a connection, then it has no effect and is useless. Therefore it must be called before my program gets a chance to establish such a connection.

[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
sealed public class CascadeOnUpdateAttribute : Attribute
{
    public bool Flag { get; private set; }

    public CascadeOnUpdateAttribute() : this(true) { }

    public CascadeOnUpdateAttribute(bool flag)
    {
        Flag = flag;
    }

    static CascadeOnUpdateAttribute()
    {
        var targets = from assembly in AppDomain.CurrentDomain.GetAssemblies()
          from type in assembly.GetTypes()
          from attribute in type.GetCustomAttributes(typeof(CascadeOnUpdateAttribute), false).Cast<CascadeOnUpdateAttribute>()
          select new { Type = type, Cascade = attribute.Flag };

        foreach (var target in targets)
        {
            Db4oFactory.Configure().ObjectClass(target.Type).CascadeOnUpdate(target.Cascade);
        }
    }
}

Update:

I ended up using an abstract attribute with a static method. This way I can derive as many attributes as I like and they will all be applied to a specified config by calling this one method.

public abstract class Db4oAttribute : Attribute
{
    public abstract void Configure(IConfiguration config, Type type);

    public static void ApplyAttributes(IConfiguration config)
    {
        var targets = from assembly in AppDomain.CurrentDomain.GetAssemblies()
          from type in assembly.GetTypes()
          from attribute in type.GetCustomAttributes(typeof(Db4oAttribute), false).Cast<Db4oAttribute>()
          select new { Type = type, Attribute = attribute };

        foreach (var target in targets)
        {
            target.Attribute.Configure(config, target.Type);
        }
    }
}

And the call site:

Db4oAttribute.ApplyAttributes(Db4oFactory.Configure());
_db = Db4oFactory.OpenFile("Test.db4o");

解决方案

As Marc says, I would do it explicitly in Main if I were you.

You can invoke the type initializer for a type explicitly using the Type.TypeInitializer property and invoking it. However, this will cause it to run again even if it's already been run which could produce unexpected results.

I would personally move that code out of the static initializer completely. It's configuration code - why not just make it a static method which you can call explicitly? I'm not even sure I'd have it in the attribute class itself, but at least explicitly calling:

CascadeOnUpdateAttribute.ConfigureDb4oFactories();

is clearer than calling a dummy method or forcing type initialization some other way, just to get a side effect.

这篇关于当控制静态构造函数被调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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