简体   繁体   English

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

[英]How would I configure ninject to use the base factory for all derived types of that class?

Given a base class in which we are supposed to use static factory methods to construct all derived classes, how would I bind such that derived types are created by the base factory? 给定一个我们应该使用静态工厂方法构造所有派生类的基类,我将如何绑定以便派生类型由该基工厂创建?

 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
    }

Sample snippet of derived class: 派生类的样本片段:

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
}

so I want to (by convention) hook up all derived types to use the base class factory method GetInstance(string) 所以我想(按照惯例)连接所有派生类型以使用基类工厂方法GetInstance(string)

how can I do this without changing the base or derived classes? 如何在不更改基类或派生类的情况下做到这一点?

This is how you could do that: 这是您可以这样做的方式:

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]);
    }
}

Disclaimer: i didn't test the reflection stuff but i think it's correct. 免责声明:我没有测试反射的东西,但我认为这是正确的。

Also note that i think it's bad design. 另请注意,我认为这是不好的设计。 I think it's a bit smelly. 我觉得有点臭。

Why are you even using the .GetInstance method? 为什么还要使用.GetInstance方法? You could just as easily replace it with: 您可以轻松地将其替换为:

this.Bind(x => x
    .FromThisAssembly()
    .SelectAllClasses()
    .InheritedFrom(typeof(BusinessObject<>))
    .BindToSelf()
    .Configure(x => x.InSingletonScope()));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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