In my static custom attribute constructor, I look at the loaded assembly for all classes decorated with my attribute and perform some actions on them.
I would like the static constructor to be called as soon as possible at runtime, preferably before the static void Main() entry point is executed.
Currently, it is called only after I called some call to this attribute. I could make such a call elsewhere in my program, but ideally, the attribute functionality would be autonomous.
Looking for answers, I read this on MSDN :
The user cannot control when the static constructor is executed in the program.
But, of course, there is some tricky, crafty, or mischievous workaround to get the static constructor to be called by ASAP. Perhaps you can use an attribute, reflection, or some other magic. Can this be done?
Because people will undoubtedly tell me that there is no reason to do what I ask, I present my purpose and my code: I try to use attributes to declaratively configure the db4o factory. If my static constructor attribute is called after I have already established a connection, it has no effect and is useless. Therefore, it must be called before my program gets the opportunity 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. That way, I can get as many attributes as I like, and they will all be applied to the 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");