Не ленивый статический блок инициализации в C # - PullRequest
5 голосов
/ 21 декабря 2010

Мне нужно запустить некоторый код, чтобы зарегистрировать тип для фабричного шаблона. Я сделал бы это в Java со статическим блоком инициализации или в C ++ со статическим конструктором.

Как вы делаете это в C #? Этот статический конструктор запускается лениво, и, поскольку тип никогда не будет указан в коде, он никогда не будет зарегистрирован.

РЕДАКТИРОВАТЬ: Я попробовал тест, чтобы увидеть работу регистрационного кода. Похоже, это не работает.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

[assembly: AssemblyTest.RegisterToFactory("hello, world!")]

namespace AssemblyTest
{
    [AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = true)]
    sealed class RegisterToFactoryAttribute : Attribute
    {
        public RegisterToFactoryAttribute(string name)
        {
            Console.WriteLine("Registered {0}", name);
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
        }
    }
}

Ничего не печатается.

1 Ответ

4 голосов
/ 21 декабря 2010

Как насчет конструктора для assembly level attribute?

Пример:

[AttributeUsage(AttributeTargets.Assembly, Inherited = false, AllowMultiple = true)]
sealed class RegisterToFactoryAttribute : Attribute
{
    public Type TypeToRegister { get; set; }

    public RegisterToFactoryAttribute(Type typeToRegister)
    {
        TypeToRegister = typeToRegister;

        // Registration code
    }
}

Использование:

[assembly:RegisterToFactory(typeof(MyClass))]

- РЕДАКТИРОВАТЬ на атрибутах уровня сборки -

После некоторого исследования я решил, что он будет загружать атрибуты сборки только в том случае, если они запрашиваются:

Пример:

object[] attributes =
    Assembly.GetExecutingAssembly().GetCustomAttributes(
        typeof(RegisterToFactoryAttribute), false);

или

object[] attributes =
    Assembly.GetExecutingAssembly().GetCustomAttributes(false);

Не знаю почему, но если поставить этот код @, загрузка программы должна это сделать.

- EDIT -

Я почти забыл:

Рассматривали ли вы использование MEF ?? Это отличное решение этой проблемы.

Пример: * * тысяча тридцать-один class MyFactory { [ImportMany("MyFactoryExport")] public List<Object> Registrations { get; set; } public MyFactory() { AssemblyCatalog catalog = new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly()); CompositionContainer container = new CompositionContainer(catalog); container.ComposeParts(this); } } [Export("MyFactoryExport")] class MyClass1 { } [Export("MyFactoryExport")] class MyClass2 { } [Export("MyFactoryExport")] class MyClass3 { }

...