如何配置ninject以将基础工厂用于该类的所有派生类型?

时间:2014-03-06 14:37:55

标签: c# ninject

给定一个基类,我们应该使用静态工厂方法来构造所有派生类,我将如何绑定,以便派生类型由基础工厂创建?

 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)

如何在不更改基类或派生类的情况下执行此操作?

1 个答案:

答案 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()));