Factory interface definition
/// <summary>
/// Factory interface definition
/// </summary>
/// <remarks>
/// TTarget : abstract product type
/// TSource: concrete product type
/// </remarks>
public interface IFactory
{
#region config and register type mapping
/// <summary>
/// If you need to load the mapping relationship defined in the configuration file at the same time, you can define independent configuration types according to the principles of SRP.
/// The two interfaces are called by this configuration type to load configuration information for Factory
/// </summary>
IFactory RegisterType<TTarget, TSource>(); // fluent interface
IFactory RegisterType<TTarget, TSource>(string name); // fluent interface
#endregion
#region factory method
TTarget Create<TTarget>();
TTarget Create<TTarget>(string name);
#endregion
}
Registration Class
public sealed class TypeRegistry
{
readonly string DefaultNmae = ().ToString();
IDictionary<Type, IDictionary<string, Type>> registry = new Dictionary<Type, IDictionary<string, Type>>();
public void RegisterType(Type targetType,Type sourceType)
{
RegisterType(targetType, sourceType, DefaultNmae);
}
public void RegisterType(Type targetType, Type sourceType,string name)
{
if (targetType == null) throw new ArgumentNullException("targetType");
if (sourceType == null) throw new ArgumentNullException("sourceType");
if ((name)) throw new ArgumentNullException("name");
IDictionary<string, Type> subDictionary;
if (!(targetType, out subDictionary))
{
subDictionary = new Dictionary<string, Type>();
(name, sourceType);
(targetType, subDictionary);
}
else
{
if ((name))
throw new DuplicateKeyException(name);
(name, sourceType);
}
}
public Type this[Type targetType, string name]
{
get
{
if (targetType == null) throw new ArgumentNullException("targetType");
if ((name)) throw new ArgumentNullException("name");
if (() == 0)
return null;
return (registry
.Where(x => == targetType)).FirstOrDefault().Value
.Where(x => (name, ))
.FirstOrDefault().Value;
}
}
public Type this[Type targetType]
{
get { return this[targetType, DefaultNmae]; }
}
}
Factory
public class Factory : IFactory
{
protected TypeRegistry registry = new TypeRegistry();
#region IFactory Members
public IFactory RegisterType<TTarget, TSource>()
{
(typeof(TTarget), typeof(TSource));
return this;
}
public IFactory RegisterType<TTarget, TSource>(string name)
{
(typeof(TTarget), typeof(TSource), name);
return this;
}
public TTarget Create<TTarget>()
{
return (TTarget)(registry[typeof(TTarget)]);
}
public TTarget Create<TTarget>(string name)
{
return (TTarget)(registry[typeof(TTarget), name]);
}
#endregion
}
Call
[TestMethod]
public void CreateInstance()
{
var factory = new Factory()
.RegisterType<IFruit, Apple>()
.RegisterType<IFruit, Orange>("o")
.RegisterType<IVehicle, Bicycle>()
.RegisterType<IVehicle, Bicycle>("a")
.RegisterType<IVehicle, Train>("b")
.RegisterType<IVehicle, Car>("c");
(<IFruit>(), typeof(Apple));
(<IFruit>("o"), typeof (Orange));
(<IVehicle>(), typeof(Bicycle));
(<IVehicle>("a"), typeof(Bicycle));
(<IVehicle>("b"), typeof(Train));
(<IVehicle>("c"), typeof(Car));
}
In fact, the essence lies in the registration class's assembly-like function, which is encapsulated through dictionary, and then compared through generics, or a new instantiation is achieved through the configuration file.
Pay attention to coherent interfaces, generics, etc.