Update Two common functions to use Generics

前端 未结 2 1083
梦毁少年i
梦毁少年i 2021-01-21 19:44

Using Microsoft Unit Test Wizard, it creates Accessor objects if you need to test a non-public property in another project. Inside my Unit Tests I create helper functions so tha

2条回答
  •  执念已碎
    2021-01-21 20:10

    You should add constraint to the generic function, because of this two methods:

    account.Notes = Utilities.RandomString(1000);
    account.Create();
    

    I suggest you to add some interface with this two methods and add inheritance from it to your two classes. Constraint should be as follows:

    where T : YourNewInterface
    

    About constraints you can read at http://msdn.microsoft.com/en-us/library/bb384067.aspx

    UPDATE

    public interface IAccount
        {
            string Notes { get; set; }
            void Create();
            void Init(DateTime created, string createdBy);
        }
    
    public class Account : IAccount
    {
        public string Notes
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }
    
        public void IAccount.Create()
        {
            throw new NotImplementedException();
        }
    
        void IAccount.Init(DateTime created, string createdBy)
        {
            throw new NotImplementedException();
        }
    }
    
    public class Account_Accessor : IAccount
    {
    
        string IAccount.Notes
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }
    
        public void IAccount.Create()
        {
            throw new NotImplementedException();
        }
    
        void IAccount.Init(DateTime created, string createdBy)
        {
            throw new NotImplementedException();
        }
    }
    
    
    class Program
    {
        internal static void CreateAccount(out T account, bool saveToDatabase) where T : IAccount,new()
        {
            DateTime created = DateTime.Now;
            string createdBy = _testUserName;
    
            account = new T();
            account.Init(created, createdBy);
    
            account = (T)Activator.CreateInstance(typeof(T), new object[] { created, createdBy });
    
            account.Notes = Utilities.RandomString(1000);
    
            if (saveToDatabase)
                account.Create();
        }
        static void Main(string[] args)
        {
            Account acc;
            Account_Accessor acc2;
            CreateAccount(out acc, false);
            CreateAccount(out acc2, false);
        }
    }
    

    Here is some comments about my example:
    1. I've replaced CreateInstance by adding new() constraint.
    2. Because new() constraint can't have parameters because of .NET generic limitations, I've added Init() method to the IAccount interface.
    3. Init method should not be called by client code of the Account class, that's why we define the method as private and explicitly for IAccount.
    4. Because of new() constraint you should provide parameterless constructor for Account. If you do this, your client code should not call this parameterless ctor.

    As for me I'd leave Activator.CreateInstance as is. It is good workaround for the limitations of generic new() constraint

提交回复
热议问题