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.