As my previous article dealt on the .NET configuration system, so shall this one. For today, I’d like to talk about the concept and implementation of named configuration elements, and how they can make implementing your configuration infrastructure simpler.

What Are Named Configuration Elements?

Named configuration elements are configuration elements that use an assigned name as their keys. They are able to exist as part of a collection of other named configuration elements, and have children of their own as well.

The idea for named configuration elements comes from the way configuration is handled with Microsoft’s Enterprise Library. I very much enjoyed the way they had their configuration entities set up, and I decided the approach would be useful in contexts outside the library.

The following code shows what a base named configuration element looks like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
/// <summary>
/// Provides a <see cref="ConfigurationElement"/> where its name is used as its key.
/// </summary>
public class NamedConfigurationElement : ConfigurationElement
{
    /// <summary>
    /// The schema name for this element's identifying attribute which holds a literal name for
    /// this element.
    /// </summary>
    private const string NAME_ATTRIBUTE = "name";
 
    /// <summary>
    /// Gets or sets the identifying name for this configuration element.
    /// </summary>
    [ConfigurationProperty(NAME_ATTRIBUTE, IsKey=true, IsRequired=true)]
    [StringValidator(MinLength=1)]
    public string Name
    {
        get { return (string) base[NAME_ATTRIBUTE]; }
        set { base[NAME_ATTRIBUTE] = value; }
    }
 
    /// <summary>
    /// Creates a <see cref="ConfigurationProperty"/> object for the <see cref="Name"/>
    /// configuration property, to be used when creating this configuration element using
    /// the programmatic model.
    /// </summary>
    protected static ConfigurationProperty CreateNameProperty()
    {
        return new ConfigurationProperty(NAME_ATTRIBUTE,
                                         typeof(string),
                                         String.Empty,
                                         null,
                                         null,
                                         ConfigurationPropertyOptions.IsKey
                                         | ConfigurationPropertyOptions.IsRequired);
    }
}

Let’s take a moment to go over what I’m doing here.

You may notice immediately that this class is not abstract. Thus, while it is very much intended for more complex elements to derive from this class, it can also be used as it is in its current form.

Because this class is meant to be used as a base for other elements, however, it needs to support both coding models used to define a configuration infrastructure. More information regarding the two different configuration coding models can be found in my previous article.

Thus, you’ll see that the lone public property (Name), is decorated with an attribute. If a subclass is derived from this class, then, and the developer wishes to use the declarative coding model, then they will be able to do so successfully, given the fact that the base properties are attributed.

Take note, however, that decorating the property with an attribute does not automatically imply that the declarative model must or even will be used. If a subclass of this class wishes to use the programmatic model instead, then they would be able to do so with no problem.

The only thing that could come up as a problem if the programmatic coding model was used, however, is that they would need to provide an initialized ConfigurationProperty object in their overridden ConfigurationPropertyCollection member. There’s a good chance they might not have the source for this class in front of them, and we don’t want them to have to break out any sort of source review tool either.

Therefore, a static helper method is provided in the form of the CreateNameProperty. When a subclass is initializing their property collection, they can simple call this method, and they will have the initialized ConfigurationProperty object that they require.

Named Element Collections

While named configuration elements are nice and all, they aren’t very useful if we don’t have the infrastructure that can host them in a collection. That’s where the NamedElementCollection<TElement> type comes into play.

Let’s take a look at what this collection class looks like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/// <summary>
/// Provides a collection of <see cref="NamedConfigurationElement"/> objects.
/// </summary>
/// <typeparam name="TElement">
/// The type of configuration element contained by the collection.
/// </typeparam>
[ConfigurationCollection(typeof(NamedConfigurationElement))]
public class NamedElementCollection<TElement> : ConfigurationElementCollection
    where TElement : NamedConfigurationElement, new()
{
    /// <inheritdoc/>
    protected override ConfigurationElement CreateNewElement()
    {
        return new TElement();
    }
 
    /// <inheritdoc/>
    protected override object GetElementKey(ConfigurationElement element)
    {
        TElement typedElement = element as TElement;
 
        // If this returns null, the built-in class this derives from will throw and exception
        // anyway, complaining about the wrong type. So we let that handle it.
        return null == typedElement
                   ? null
                   : typedElement.Name;
    }
}

This rather simple class is all we need then to put these named configuration elements to use. In my actual code, I have this type derived from a more specialized base class (ConfigurationElementCollection<TElement, TKey>), which provides some more functionality as well as implementing the IEnumerable<T> interface, however we don’t need that for the purposes of this article.

You’ll notice that the class itself is attributed with a ConfigurationCollectionAttribute. The documentation available from Microsoft typically shows that attribute being used where the type is being declared as a member, not on the class itself.

Well, interestingly enough, Microsoft almost always decorates the custom collection classes at their definition, like how I am doing it, as opposed to the former method. By doing it at the class level, it seems that we can alleviate the people putting to use from having to fulfill on that requirement; however, they certainly can re-declare the attribute on the member if they need to change its configuration.

Putting It to Use (Declaratively)

Let’s quickly design a configuration infrastructure using these elements, and then see what the resulting configuration would look like.

This infrastructure I want is ultimately going to use the programmatic model, however, let’s first take a look at one designed to use the declarative model. One benefit of using the declarative model is I don’t need to do subclass my NamedConfigurationElement class if I don’t need to add any additional functionality to it.

So, let’s skip straight to our custom configuration section class using the declarative model:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/// <summary>
/// Provides a configuration section for hosting a number of configured categories used by the
/// application somehow.
/// </summary>
public sealed class CategoriesSection : ConfigurationSection
{
    /// <summary>
    /// The schema name for the child collection element containing all of the categories.
    /// </summary>
    private const string CATEGORIES_CHILD = "categories";
 
    /// <summary>
    /// Gets the collection of categories.
    /// </summary>
    [ConfigurationProperty(CATEGORIES_CHILD)]
    public NamedElementCollection<NamedConfigurationElement> Categories
    {
        get { return (NamedElementCollection<NamedConfigurationElement>) base[CATEGORIES_CHILD]; }
    }
 
    // I normally have some additional helper methods here for every section I write, but they don't
    // affect the topic at hand.
}

And that’s it! We don’t have to do anything else. Let’s look at what our configuration in XML would look like, assuming the name for our section is declared as “categoriesSection”:

1
2
3
4
5
6
<categoriesSection>
  <categories>
    <add name="FirstCategory" />
    <add name="SecondCategory" />
  </categories>
</categoriesSection>

Pretty slick.

Putting It to Use (Programmatically)

Let’s design our infrastructure using the programmatic model instead. Using the programmatic model requires us to create a subclass for each individual element, as they won’t override their ConfigurationPropertyCollection on their own.

Because our configuration is intended to host category elements, and because we’re using the programmatic model, we’ll need to define aCategoryElement class. Since we’re going ahead and defining a class, let’s add an additional capability to these category elements in that each one can host one or more subcategories.

Next, let’s look at our CategoryElement class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
/// <summary>
/// Provides a configuration element for a category.
/// </summary>
public sealed class CategoryElement : NamedConfigurationElement
{
    /// <summary>
    /// The schema name for the child collection containing all of the subcategories.
    /// </summary>
    private const string SUBCATEGORIES_CHILD = "subCategories";
 
    private static readonly Lazy<ConfigurationPropertyCollection> _Properties
        = new Lazy<ConfigurationPropertyCollection>(InitializeProperties,
                                                    LazyThreadSafetyMode.PublicationOnly);
 
    /// <summary>
    /// Gets the collection of subcategories.
    /// </summary>
    public NamedConfigurationElement<CategoryElement> Subcategories
    {
        get { return (NamedConfigurationElement<CategoryElement>) base[SUBCATEGORIES_CHILD]; }
    }
 
    /// <inheritdoc/>
    protected override ConfigurationPropertyCollection Properties
    {
        get { return _Properties.Value; }
    }
 
    /// <summary>
    /// Creates a <see cref="ConfigurationPropertyCollection"/> object containing all configuration
    /// properties belonging to this element.
    /// </summary>
    private static ConfigurationPropertyCollection InitializeProperties()
    {
        return
            new ConfigurationPropertyCollection
                {
                    new ConfigurationProperty(SUBCATEGORIES_CHILD,
                                              typeof(NamedConfigurationElement<CategoryElement>),
                                              null,
                                              ConfigurationPropertyOptions.None),
                    CreateNameProperty()
                };
    }
}

Very simple, not much is needed to explain here, although if you’re asking any questions about any particular approach made above, I’d refer you to my previous article. Let’s then finally look at our CategoriesSection, which has been modified to use the programmatic model:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
/// <summary>
/// Provides a configuration section for hosting a number of configured categories used by the
/// application somehow.
/// </summary>
public sealed class CategoriesSection : ConfigurationSection
{
    /// <summary>
    /// The schema name for the child collection element containing all of the categories.
    /// </summary>
    private const string CATEGORIES_CHILD = "categories";
 
    private static readonly Lazy<ConfigurationPropertyCollection> _Properties
        = new Lazy<ConfigurationPropertyCollection>(InitializeProperties,
                                                    LazyThreadSafetyMode.PublicationOnly);
 
    /// <summary>
    /// Gets the collection of categories.
    /// </summary>
    public NamedElementCollection<NamedConfigurationElement> Categories
    {
        get { return (NamedElementCollection<NamedConfigurationElement>) base[CATEGORIES_CHILD]; }
    }
 
    /// <summary>
    /// Creates a <see cref="ConfigurationPropertyCollection"/> object containing all configuration
    /// properties belonging to this element.
    /// </summary>
    private static ConfigurationPropertyCollection InitializeProperties()
    {
        return
            new ConfigurationPropertyCollection
                {
                    new ConfigurationProperty(CATEGORIES_CHILD,
                                              typeof (NamedElementCollection<NamedConfigurationElement>),
                                              null,
                                              null,
                                              null,
                                              ConfigurationPropertyOptions.None)
                };
    }
 
    // I normally have some additional helper methods here for every section I write, but they don't
    // affect the topic at hand.
}

Not too much needed to be added here, just the necessary infrastructure for overriding the Properties method.

Let’s then wrap up things by taking a look at what the configuration may look like:

1
2
3
4
5
6
7
8
9
10
11
<categoriesSection>
  <categories>
    <add name="FirstCategory">
      <subCategories>
        <add name="Frisky" />
        <add name="EasilyJealous" />
      </subCategories>
    </add>
    <add name="SecondCategory" />
  </categories>
</categoriesSection>

Very nice, in my opinion.

 

Some easy reading for today.

I recently completed the process of designing and implementing the configuration layer for my company’s new platform. As with everything I’m doing with the new product, a practical amount of care and consideration was devoted towards ensuring that this particular piece was being committed in a manner as correct as possible.

I’ve dealt with .NET’s configuration system more than once, but for this I decided to take a closer look at some of the MSDN documentation and existing Microsoft configuration-related code. I was surprised to learn that there are two completely separate models to follow when implementing the various custom configuration types.

This article covers these models. Not the most exotic subject in the world (indeed, a very simple subject), and one that already has some fairly excellent writings dedicated to it already; I was unable to find a clear and concise overview of the matter however.

Configuration Coding Models

The declarative coding model is the one which I would argue is the more “famous” of the two; indeed it seems to be the way it is taught to the masses, both by Microsoft and other entities. The declarative coding model involves the use of those configuration attributes we all know and love, such as ConfigurationCollectionAttribute, which would go over properties meant to return a collection of configuration elements.

The other model is referred to as the programmatic coding model. This model is notable in that it seems to be the preferred approach taken by Microsoft for what seems to be every custom configuration element defined in the .NET Framework. In fact, spotting this pattern is truly what lead me to take some time looking for additional information in the first place. Given the frequency of its occurrence in the .NET Framework, one could make the assertion that use of the programmatic coding model within Microsoft’s code is company policy.

I pay great attention to matters like this. Time and time again, with regards to various Microsoft technologies, I’ve observed instances of a dual dichotomy of recommended methodologies and techniques to aid the consumption of said technologies. There will be one set of methodologies and techniques fervently evangelized and marketed for public consumption, and then there will be a lesser spoken of set of methodologies and techniques which tend to exhibit the characteristics of being both the more “correct” way of doing things as well as happening to be the way Microsoft approaches the use of the technology internally.

An example of this phenomenon is VSTO. VSTO is the very publicly touted way to do Office extensibility when using the .NET Framework as your platform. In actuality, if your intent is to create an add-in that is more than a very minor product feature, VSTO is insufficient and a very poor way to go about it. You will increase your development time, drive up your support bills, and be unable to deliver to some key demographics due to technological limitations.

The instance of this phenomenon that we have here with the configuration system is not anywhere near as severe as some others, and barely even qualifies for the distinction; regardless of barely qualifying as an instance of this described phenomenon, I’d argue that it still does qualify.

But I digress, and I’ve already written a piece on what I just wrote above.

Model time.

Declarative Coding Model

The declarative coding model is the simpler of the two models, and will require less time in order to get something from nothing to out the door.

The rules imposed by this model are simple (if not a bit unclear at times) in that you need to decorate configuration element properties with the appropriate ConfigurationPropertyAttribute, which is also where you provide the configuration for those elements as well.

Clearly, those attributes are defined so they may be read during runtime by the Framework itself. Being attributes, Reflection is used in order to do just that. Once this information has been obtained by the framework’s configuration system, the element property objects will be created and initialized appropriately.

Here’s an example of a configuration section using the declarative approach:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/// <summary>
/// Provides a very useful configuration section.
/// </summary>
public sealed class VeryUsefulSection : ConfigurationSection
{
    /// <summary>
    /// The schema name for the child element containing the most useful thing in existence.
    /// </summary>
    private const string MOST_USEFUL_CHILD = "mostUseful";
 
    /// <summary>
    /// The schema name for the child collection element containing all of the stuff in the universe
    /// deemed to be useful.
    /// </summary>
    private const string USEFUL_STUFF_CHILD = "usefulStuff";
 
    /// <summary>
    /// Gets or sets the configuration element containing the most useful thing in existence.
    /// </summary>
    [ConfigurationProperty(MOST_USEFUL_CHILD, IsRequired=true)]
    public UsefulElement MostUseful
    {
        get { return (UsefulElement) base[MOST_USEFUL_CHILD]; }
        set { base[MOST_USEFUL_CHILD] = value; }
    }
 
    /// <summary>
    /// Gets the collection of all the stuff in the universe deemed to be useful.
    /// </summary>
    [ConfigurationProperty(MOST_USEFUL_CHILD, IsRequired=true)]
    [ConfigurationCollection(typeof(UsefulElement))]
    public UsefulElements UsefulStuff
    {
        get { return (UsefulElements) base[USEFUL_STUFF_CHILD]; }
    }
 
    // I normally have some additional helper methods here for every section I write, but they don't
    // affect the topic at hand.
}

As the above code makes very evident, what we have here is a configuration section that deals with really useful stuff.

Take a look at the properties of the section. Each property here corresponds to a configuration element in a file. Each one also has one or more configuration-related attributes decorating them.

Take a look at the MostUseful property. This property returns a UsefulElement type object, which would correspond to a single<usefulElement>-like XML element in a configuration file. It is being decorated with a single ConfigurationProperty attribute.

Then we have the UsefulStuff property. This returns a UsefulElements type object, which is actually an implementation of theConfigurationElementCollection type, responsible for returning multiple UsefulElement type objects. Not only does this property have a ConfigurationProperty element, but a ConfigurationCollection attribute as well.

All of the various attributes shown above and how they are used fall in line with the declarative coding model. At runtime, these configuration elements will be reflected through, information will be discovered, and then the necessary objects will be created.

Programmatic Coding Model

Now, onto the other model available for us to use: the programmatic coding model, or as I like to call it, the way Microsoft does it.

Why is there even another model? Isn’t the model we just went over a shining example of the pinnacle of human ingenuity in regards to configuration-related structure creation? Oh it could very well have been just that, if not for a few issues.

  1. Using the declarative model infers that the primary method of information discovery used will be reflection. So there is a performance cost with that, you decide how important that is to you.
  2. And then, on another performance-related note: the result of the process that creates the actual configuration elements is not cached, at least not fully. This means that there will be some type of cost incurred each time you need to load a configuration-related element.
  3. Sometimes attributes can be a real pain in the ass! Though, I do normally love attributes; for some reason their use in conjunction with the .NET configuration system fouls my mood.

Implementing a configuration element type using the programmatic coding model is actually a very simple affair. All we need to do is override the type’s Properties property, which returns a ConfigurationPropertyCollection object.

Let’s a take a look at the code for the same section as the one defined in the previous section, but one that is based on the programmatic coding model instead:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
/// <summary>
/// Provides a very useful configuration section.
/// </summary>
public sealed class VeryUsefulSection : ConfigurationSection
{
    /// <summary>
    /// The schema name for the child element containing the most useful thing in existence.
    /// </summary>
    private const string MOST_USEFUL_CHILD = "mostUseful";
 
    /// <summary>
    /// The schema name for the child collection element containing all of the stuff in the universe
    /// deemed to be useful.
    /// </summary>
    private const string USEFUL_STUFF_CHILD = "usefulStuff";
 
    private static readonly Lazy<ConfigurationPropertyCollection> _Properties
        = new Lazy<ConfigurationPropertyCollection>(InitializeProperties,
                                                    LazyThreadSafetyMode.PublicationOnly);
 
    /// <summary>
    /// Gets or sets the configuration element containing the most useful thing in existence.
    /// </summary>
    public UsefulElement MostUseful
    {
        get { return (UsefulElement)base[MOST_USEFUL_CHILD]; }
        set { base[MOST_USEFUL_CHILD] = value; }
    }
 
    /// <summary>
    /// Gets the collection of all the stuff in the universe deemed to be useful.
    /// </summary>
    public UsefulElements UsefulStuff
    {
        get { return (UsefulElements)base[USEFUL_STUFF_CHILD]; }
    }
 
    /// <inheritdoc/>
    protected override ConfigurationPropertyCollection Properties
    {
        get { return _Properties.Value; }
    }
 
    /// <summary>
    /// Creates a <see cref="ConfigurationPropertyCollection"/> object containing all configuration
    /// properties belonging to this element.
    /// </summary>
    private static ConfigurationPropertyCollection InitializeProperties()
    {
        return
            new ConfigurationPropertyCollection
                {
                    new ConfigurationProperty(MOST_USEFUL_CHILD,
                                              typeof (UsefulElement),
                                              null,
                                              ConfigurationPropertyOptions.IsRequired),
                    new ConfigurationProperty(USEFUL_STUFF_CHILD,
                                              typeof (UsefulElements),
                                              null,
                                              ConfigurationPropertyOptions.IsRequired)
                };
    }
}

There it is. As you can see, we no longer have to deal with attributes, although we still have to ultimately provide the element-related configuration in the InitializeProperties initializer method. We now provide a static field named _Properties which will maintain a static reference to our element information. The value behind this is ultimately returned in the Properties override, which is also new from the old code.

Details, Details!

Why do we have the value for the configuration properties stored in a static field? Because I only want to have to initialize the data once per type per application domain lifecycle. Whether it saves a minute or a billionth of a nanosecond, it doesn’t matter, because it’s simply logical that you would only initialize something whose parameters are defined at compile-time once.

A better question is: Why do I have the configuration properties wrapped with Lazy<T>? That’s a good question. Let’s go over some points related to that.

  • Because we’re playing with static fire here, we of course need to make sure we aren’t shooting ourselves in the face in regards to threading issues.
  • Static field initializers are guaranteed to be thread-safe, as they’re only executed one per application domain lifecycle.

OK. Wait a second, it sounds like that a justification was just made to use a simpler static field initialization of theConfigurationPropertyCollection as opposed to delaying the initialization by wrapping it with a Lazy<T>.

Indeed, you might be 100% fine if you just stick to a static field initializer. The example code I’ve provided is influenced a bit by the platform I’ve been working on that my company’s products will be based on. So, I have a few requirements that led me to choose to use a Lazy<T> type.

And by the way, the reason why I’m even going over these reasons is because, while the use of Lazy<T> just by itself by a developer would frankly (and unfortunately) be impressive to myself, using it to be lazy for the sake of being lazy (in other words: you have no reason) would do well to cause me to question the competency of the developer. It’s also an interesting discussion.

The reason I’m lazily initializing the property collection is because it is possible that an application based off of the platform these configuration classes might run without ever actually needing to use them. Why spend time performing work if you don’t need to perform that work? When the solution to that is as simple as wrapping a type with a Lazy<T>, why not? The solution can be provided unconsciously even.

But hold on…if an application never uses these configuration files, then wouldn’t the static field initializers never go off? If you’re vaguely familiar with static initialization and the C#/CLR specs, you might think that to be case.

However, that’s not necessarily the case. In fact, with .NET 4.0, static field initialization now occurs at an “implementation-dependent” time. In other words, static field initialization, while appearing to be based on a lazy strategy itself, gives absolutely no guarantees or actual guidance as to when it might occur.

But wait! Why don’t we just move the static fields into a static constructor? Yes, if we define an explicit static constructor, we suddenly have deterministic time of initialization. Indeed, the spec states that a static constructor will be triggered if one of the following events occur:

  • An instance of the class type is created.
  • Any of the static members of the class type are referenced.

Ah, so going with the first point there, know that by avoiding all use of instances of these configuration types we avoid the initialization routine from firing due to the first condition defined above.

But the second condition is what kills the approach of using a static constructor. In the actual platform code, there are some static properties on these types that may be referred to without ever reading the configuration itself. These properties were not included, and they’ll not be discussed as they are both outside the topic and proprietary (and plus, I don’t feel like it!)

Now, how long did it take me to reason the above and use a Lazy<T> to hold the properties while I was actually writing my platform code? Probably 10 seconds max. Articulating this reason in writing certainly added some time onto that, however.

The point I’m making here is that if spending more than 10 seconds on a decision like the one just made could be considered a waste of time.

 

I’ve been busy designing and building my company’s new product, so I haven’t had much time to write lately.

In a previous article I wrote, I went into depth regarding the various ways we could perform validation on method parameters using PostSharp. At the conclusion of that article, we ended up with a solution that gave us what we wanted: a way to designate individual parameters as needing validation at runtime simply by decorating each parameter with a single validation attribute.

Of course, that solution was the result of a wanton foray into the bowels of PostSharp, with the bowels in particular being that of theundocumented variety. So, hopefully no one was conducting themselves while being under a false pretext that our results were guaranteed to be stable. I know I wasn’t!

I have, since writing that article, happened to run into one particular side effect of the custom woven validation attribute worth some quick discussion.

Where’s mah ‘beforefieldinit’?

Indeed.

I noticed recently (whether it was due to us emitting some additional instructions in the static constructor or simply because of our use of a custom IAdvice implementation) that all classes containing any methods sporting parameters decorated by one of our validation attributes were being stripped of their beforefieldinit flags.

I won’t spend anyone’s precious time redundantly going over what exactly the beforefieldinit flag is (here’s a good source) but it’s certainly something our validation attributes shouldn’t be touching. Our advice does not depend on the order of initialization of any static fields other than its own in the classes it ends up getting applied to, so it is safe to say that our advice supports the beforefieldinit flag.

After poking around a bit in the SDK, I happened upon an interface eloquently titled IBeforeStaticConstructorAdvice, which basically allows us to express to the weaver whether or not our advice supports the beforefieldinit flag.

Adding Support for ‘beforefieldinit’

To get our beforefieldinit flag back, we simply need to replace the IAdvice interface being implemented by our base advice class with the IBeforeStaticConstructorAdvice interface (which itself implement IAdvice), and return true for the sole required method (not 100% if I posted the base class in the last article; should be enough to get the point across):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public abstract class ValidationAdvice<TValidationAttribute>
  : IBeforeStaticConstructorAdvice, IDisposable
{
  .
  .
  .
  public bool IsBeforeFieldInitSupport
  {
    get { return true; }
  }
  .
  .
  .
}
© 2012-2013 Matt Weber. All Rights Reserved. Terms of Use.