不从类B的静态构造函数中调用类A的静态方法

时间:2014-06-30 10:32:40

标签: c# oop

我有以下课程

    public class A
    {

        protected static Dictionary<string,Func<BaseClass>> dict = new Dictionary<string,Func<BaseClass>>();

        public static void AddGenerator(string type,Func<BaseClass> fncCreateObject)
        {
            dict.Add(type,fncCreateObject);
        }

    }

    class B : BaseClass
    {
        static B()
        {
            A.AddGenerator("b",CreateObject);
        }

        protected B()
        {}

        pulic static B CreateObject()
        {
            return new B();
        }
    }

注意:上面的代码只是一个例子,但与我试图实现的内容密切相关。

很多人会建议使用IoC容器,例如NInject或Unity,但是这篇文章的主要原因是要弄清楚为什么上面的代码没有像预期的那样执行。

因此,在上面的代码中,我期望B类的静态构造函数调用类A的静态方法,并且应该在字典中为应用程序生命周期的其余部分提供一个条目

但是,当我运行代码和调试时,我发现字典是空的。

为什么从B类静态构造函数调用的代码没有执行?

2 个答案:

答案 0 :(得分:4)

来自documentation

  

在创建第一个实例或引用任何静态成员之前,会自动调用静态构造函数来初始化类。

显然,在您检查字典的代码中,尚未创建任何实例,并且未引用任何静态成员。

答案 1 :(得分:1)

不完全是您的样品1:1翻译到MEF,但它应该让您知道MEF能够做什么:

using System;
using System.Collections.Generic;

namespace ConsoleApplication4
{
    using System.ComponentModel.Composition;
    using System.ComponentModel.Composition.Hosting;
    using System.Reflection;

    class Program
    {
        static void Main(string[] args)
        {
            var assemblyCatalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
            var directoryCatalog = new DirectoryCatalog(".");
            var compositeCatalog = new AggregateCatalog(assemblyCatalog, directoryCatalog);
            var container = new CompositionContainer(compositeCatalog);
            var a = A.Instance;
            container.SatisfyImportsOnce(a);
            a.PrintCatalog();
        }
    }

    public sealed class A
    {
        private static readonly A instance = new A();

        static A() { }

        private A() { }

        public static A Instance { get { return instance; } }

        [ImportMany]
        private List<IBType> BTypes;

        public void PrintCatalog()
        {
            foreach (var bType in BTypes)
            {
                Console.WriteLine(bType.GetType());
            }
        }

    }

    [Export(typeof(IBType))]
    class B:IBType
    {
        static B()
        {
        }

        protected B()
        {}

        public void DoSomething() {  }
    }

    [Export(typeof(IBType))]
    class B2:IBType
    {
        static B2()
        {
        }

        protected B2()
        {}

        public void DoSomething() {  }
    }

    interface IBType
    {
        void DoSomething();
    }

}

我还包括了我所知道的最安全的Singleton模式实现。 MEF将允许您获取在运行时动态解析的同一接口的许多实现。我也使用它metadata attributes,就像版本和名称一样。 但是,如果您需要它来使用基本抽象类,请查看this article

与上面相同的代码,但使用元数据属性使用sample:

using System;
using System.Collections.Generic;

namespace ConsoleApplication4
{
    using System.ComponentModel.Composition;
    using System.ComponentModel.Composition.Hosting;
    using System.Linq;
    using System.Reflection;

    class Program
    {
        static void Main(string[] args)
        {
            var assemblyCatalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
            var directoryCatalog = new DirectoryCatalog(".");
            var compositeCatalog = new AggregateCatalog(assemblyCatalog, directoryCatalog);
            var container = new CompositionContainer(compositeCatalog);
            var a = A.Instance;
            container.SatisfyImportsOnce(a);
            a.PrintCatalog();
            a.BTypes.Single(s=>s.Metadata.Name.Equals("Second")).Value.DoSomething();
        }
    }

    public sealed class A
    {
        private static readonly A instance = new A();

        static A() { }

        private A() { }

        public static A Instance { get { return instance; } }

        [ImportMany]
        public List<Lazy<IBType,IBTypeMetadata>> BTypes;

        public void PrintCatalog()
        {
            foreach (var bType in BTypes)
            {
                Console.WriteLine(bType.Value.GetType());
            }
        }

    }

    [Export(typeof(IBType))]
    [BTypeMetadata("First")]
    class B:IBType
    {
        static B()
        {
        }

        protected B()
        {}

        public void DoSomething() {  }
    }

    [Export(typeof(IBType))]
    [BTypeMetadata("Second")]
    class B2 : IBType
    {
        static B2()
        {
        }

        protected B2()
        {}

        public void DoSomething()
        {
            Console.WriteLine("Hello from Second");
        }
    }

    public interface IBType
    {
        void DoSomething();
    }

    public interface IBTypeMetadata
    {
        string Name { get; }
    }

    [MetadataAttribute]
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
    public class BTypeMetadataAttribute : ExportAttribute
    {
        public string Name { get; set; }
        public BTypeMetadataAttribute(string name)
            : base(typeof(IBTypeMetadata)) { Name = name; }
    }

}

恕我直言,MEF可能会帮助您,只要您的计划是从任何B类型的特定实例调用某些公共方法。在您的示例中,您只需创建一个B类型的新实例,我认为它比示例显示的更多。

MEF将从您当前加载的程序集中为您创建目录,以及来自任意数量目录的任意数量的程序集。您甚至可以动态地重新组合它,这意味着,在运行时,您可能从服务器检索DLL,并将其添加到目录中而不关闭应用程序。

MEF也是分层的,因此您的B类型可以拥有自己的“目录”。要把它连接起来,你所要做的就是调用SatifyImportsOnce传递一个A类实例。