简体   繁体   中英

How to initialize class before it is needed in the Main method using C#

Given this code:

using System;
using System.Collections.Generic;
using FactoryCallback = System.Func<System.Object>;

interface IMessageProvider
{
    string Message { get; }
}

class MessageProvider : IMessageProvider
{
    private Random generator = new Random();

    public static void Register()
    {
        InstanceFactory.Register(typeof(IMessageProvider), () => new MessageProvider());
    }

    public string Message
    {
        get
        {
            switch (generator.Next(3))
            {
                case 0:
                    return "No matter where you go, there you are.";
                case 1:
                    return "Once I thought I'd made a mistake, but I was wrong.";
                case 2:
                    return "I used to think I was indecisive; now I'm not so sure";
                default:
                    throw new IndexOutOfRangeException();
            }
        }
    }
}

class InstanceFactory
{
    private static Dictionary<Type, FactoryCallback> typeCallbacks =
        new Dictionary<Type, FactoryCallback>();

    public static void Register(Type type, FactoryCallback callback)
    {
        typeCallbacks.Add(type, callback);
    }

    public static Object InstanceOf(Type type)
    {
        return typeCallbacks[type]();
    }
}

public class RandomMessage
{
    public static void Main()
    {
        IMessageProvider provider =
            InstanceFactory.InstanceOf(typeof(IMessageProvider)) as IMessageProvider;
        Console.WriteLine(String.Format("The message is:\n{0}", provider.Message));
    }
}

This program will not run successfully as is because the MessageProvider never actually registers with the InstanceFactory. Obviously, a call to MessageProvider.Register could be added to the beginning of RandomMessage.Main. However, that now requires RandomMessage to have knowledge of MessageProvider and defeats the whole purpose of the InstanceFactory class which is intended to separate how to create something from what that something does. I would like the MessageProvider to be able to automatically register with the InstanceFactory before RandomMessage.Main tries to create an IMessageProvider instance. How could this be accomplished?

The registration of service IMessageProvider and component MessageProvider with InstanceFactory is not the responsbility of the MessageProvider implementation, it is an infrastructure concern for the application, therefore should be done inside of the Main method.

public class RandomMessage
{
    public static void Main()
    {
        // Register services with InstanceFactory at the start of Main method
        InstanceFactory.Register(typeof(IMessageProvider), () => new MessageProvider());

        IMessageProvider provider = InstanceFactory.InstanceOf(typeof(IMessageProvider)) as IMessageProvider;
        Console.WriteLine(String.Format("The message is:\n{0}", provider.Message));
    }
}

If you somehow referenced MessageProvider before calling InstanceFactory.InstanceOf() , you could just add a static constructor to MessageProvider class:

static MessageProvider()
{
    Register();
}

If it's not an option, you can do it via reflection by adding a custom attribute to all classes you want to register and calling Register() for all of them in static constructor of InstanceFactory like described here .

Consider using some Inversion of Control library. like Unity (but it might be overkill) or SimpleContainer.

Then you will 'Register' instance of interfaces while your app start (in examples you should have file like 'bootstrapper.cs' )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM