给定一个基类,我们应该使用静态工厂方法来构造所有派生类,我将如何绑定,以便派生类型由基础工厂创建?
public abstract class BusinessObject<T> where T : BusinessObject<T>, new()
{
#region Member Variables
/// <summary>
/// Object that acts as a lock when retrieving or creating the singleton instance.
/// </summary>
private static object singletonLock = new object();
/// <summary>
/// Singleton instance of this business object with default connection string.
/// </summary>
private static T instance;
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
#endregion Member Variables
#region Properties
/// <summary>
/// Gets the connection string.
/// </summary>
/// <value>The connection string.</value>
public virtual string ConnectionString { get; protected set; }
/// <summary>
/// Default connection string for business object.
/// </summary>
protected virtual string DefaultConnectionString { get { return ConfigurationManager.ConnectionStrings["LocalSqlConnection"].ConnectionString; } }
/// <summary>
/// Creates or retrieves the singleton instance of this business object.
/// </summary>
public static T Instance { get { return GetInstance(); } }
protected static log4net.ILog Log { get { return log; } }
#endregion Properties
#region Constructor
/// <summary>
/// Initializes a new instance of the <see cref="BusinessObject"/> class.
/// </summary>
protected BusinessObject()
{
ConnectionString = DefaultConnectionString;
}
#endregion Constructor
#region Methods
/// <summary>
/// Returns singleton business object using default connection string.
/// </summary>
public static T GetInstance()
{
if (instance != null)
return instance;
// If instance has not been created, create new instance (with thread-safe lock).
lock (singletonLock)
{
if (instance == null)
instance = new T();
}
return instance;
}
/// <summary>
/// Returns new instance of business object using custom connection string.
/// </summary>
public static T GetInstance(string connectionString)
{
return new T() { ConnectionString = connectionString };
}
#endregion Methods
}
派生类的示例片段:
public class ProjectBO : BusinessObject<ProjectBO>
{
#region Constructors
[Obsolete("Use instance property instead", false)]
public ProjectBO() { }
static ProjectBO()
{
quotaGroupBlacklist = new List<int>();
unavailableQuotaGroupsByMember = new Dictionary<int, List<int>>();
unavailableProjectsByMember = new Dictionary<int, List<int>>();
}
#endregion Constructors
}
所以我希望(按惯例)挂钩所有派生类型以使用基类工厂方法GetInstance(string)
如何在不更改基类或派生类的情况下执行此操作?
答案 0 :(得分:1)
这就是你如何做到的:
this.Bind(x => x
.FromThisAssembly()
.SelectAllClasses()
.InheritedFrom(typeof(BusinessObject<>))
.BindWith<BusinessObjectBindingGenerator>());
public class BusinessObjectBindingGenerator : IBindingGenerator
{
public IEnumerable<IBindingWhenInNamedWithOrOnSyntax<object>> CreateBindings(Type type, IBindingRoot bindingRoot)
{
yield return bindingRoot
.Bind(type)
.ToMethod(ctx => CreateBusinessObject(type));
}
private static object CreateBusinessObject(Type type)
{
return typeof(BusinessObject<>)
.MakeGenericType(type)
.GetMethod("GetInstance", BindingFlags.Static | BindingFlags.Public)
.Invoke(null, new object[0]);
}
}
免责声明:我没有测试反射内容,但我认为这是正确的。
另请注意,我认为这是糟糕的设计。我认为这有点臭。
为什么你甚至使用.GetInstance
方法?您可以轻松地将其替换为:
this.Bind(x => x
.FromThisAssembly()
.SelectAllClasses()
.InheritedFrom(typeof(BusinessObject<>))
.BindToSelf()
.Configure(x => x.InSingletonScope()));