如何使用属性添加静态构造函数行为?

时间:2015-06-15 13:58:48

标签: c#

我想使用属性为具有相同行为的类添加静态构造函数行为(在我的示例中为静态字段占位符替换)。

实际上我是使用一个实用程序类显式调用静态构造函数,该实用程序类使用Reflection执行静态stuf:

public class Util
{
  public static void perform(System.Type container)
  {
    // do the static stuff (basically initializing readonly fields
  }
}

public class AClass
{
  static AClass()
  {
    Util.perform(typeof(AClass));
  }
  private static readonly string A = "eza";
  private static readonly string B = "$A.dat";
}

我想以这种方式使用Utility类:

[StaticVerbatimPlaceholderSubstitution]
public class A
{
  private static readonly string A = "eza";
  private static readonly string B = "$A.dat";
}

实际上我知道如何扩展Attribute类。困扰我的是如何在合适的时间拨打电话。实际上在代码期间(在main或controller中)使用它听起来不像静态构造函数(在类的任何实例化之前)。

如果任何人可以帮助我并告诉将属性的消费代码放在哪里,我会非常高兴。

如果可以使用相同的实用程序代码(也是完成部分),那么包含引用就足以提供行为,而无需在客户端代码上进行代码调整。

谢谢,

使用代码进行编辑以进行理解:

using System;
using System.Reflection;
using System.Collections;
using System.Text.RegularExpressions;

namespace Utils
{
    /// <summary>
    /// Classe utilitaire pour initialiser les champs de chaines de caractères statiques en lecture seuls.
    /// Cette classe, permet de faire de la substitution de chaine de caractère en utilisant les expressions :
    /// ${...} qui sont remplacer sur place (verbatim) dans la chaine appelante.
    /// Si des autoréférences sont présentes, le code lève une exception TypeInitializationException lors l'appel à la classe.
    /// </summary>
    public class VerbatimPlaceHolder
    {
        public static void ReplaceAll(System.Type container)
        {
            Hashtable computed = new Hashtable();
            Hashtable visited = new Hashtable();

            FieldInfo[] fields = container.GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
            foreach (FieldInfo field in fields)
            {
                Replace(container, field, visited, computed);
            }
        }

        private static void Replace(System.Type container, FieldInfo field, Hashtable visited, Hashtable computed)
        {
            if (computed.ContainsKey(field.Name)) return;

            if (visited.ContainsKey(field.Name))
            {
                string names = "";
                foreach (string name in visited.Keys) names += (names.Length > 0 ? ", " : "") + name;
                throw new Exception("[ERREUR FATALE] autoréférence dans la définition des champs statiques {" + names + "} de la classe " + container.Name);
            }

            if (field != null && field.IsStatic && field.IsInitOnly && field.FieldType == typeof(string))
            {
                visited.Add(field.Name, field);

                string result = (string) field.GetValue(null);

                Regex placeHolderPattern = new Regex(@"\$\{([_a-zA-Z0-9]*)\}");
                foreach (Match sub in placeHolderPattern.Matches(result))
                {
                    FieldInfo node = container.GetField(sub.Groups[1].Value, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
                    if (node == null) 
                    {
                        throw new Exception("[ERREUR FATALE] le champ statique " + sub.Value + " n'est pas défini pour " + container.Name + "." + field.Name);
                    }

                    Replace(container, node, visited, computed);
                    result = result.Replace(sub.Value, (string) node.GetValue(null));
                }

                //removing space and line breaks
                Regex blanks = new Regex(@"[\s\r\n]+");
                result = blanks.Replace(result, " ");

                field.SetValue(null, result);
                computed.Add(field.Name, field);

                visited.Remove(field.Name);
            }           
        }
    }
}

1 个答案:

答案 0 :(得分:0)

好的,我想我需要用IL注入来寻找模块初始化器(根据Mono Cecile或Postsharp)。

在Web上下文中存在允许这种行为的IAssemblyPosProcessor,但这只是Web上下文,我想让库也以批处理模式工作。