更新两个常用函数以使用generics

如果需要在另一个项目中测试非公共属性,则使用Microsoftunit testing向导创建Accessor对象。 在我的unit testing中,我创建了辅助函数,这样我就不会在每个unit testing方法中重复相同的代码。 目前我有两个几乎相同的测试,除了一个采用标准对象,另一个采用Accessor版本。 由于Accessor基于标准版本,我应该能够拥有一个函数,我认为我应该能够使用generics来完成。 问题是尝试重新输入和编译失败。

以下是现有的两个function:

// Common function to create a new test record with standard Account object internal static void CreateAccount(out Account account, bool saveToDatabase) { DateTime created = DateTime.Now; string createdBy = _testUserName; account = new Account(created, createdBy); account.Notes = Utilities.RandomString(1000); if (saveToDatabase) account.Create(); } // Common function to create a new test record with Account_Accessor internal static void CreateAccount(out Account_Accessor account, bool saveToDatabase) { DateTime created = DateTime.Now; string createdBy = _testUserName; account = new Account_Accessor(created, createdBy); account.Notes = Utilities.RandomString(1000); if (saveToDatabase) account.Create(); } 

我尝试将签名更改为组合函数:

 internal static void CreateAccount(out T account, bool saveToDatabase) {...} 

但无法正确地重新计算帐户或帐户_Accessor。 有什么建议?

您应该为generics函数添加约束,因为这两种方法:

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

我建议你用这两个方法添加一些接口,并将它的inheritance添加到你的两个类中。 约束应如下:

 where T : YourNewInterface 

关于约束,您可以在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); } } 

以下是关于我的示例的一些评论:
1.我通过添加new()约束替换了CreateInstance
2.因为由于.NETgenerics限制而new()约束不能有参数,所以我在IAccount接口中添加了Init()方法。
3.不应该通过Account类的客户端代码调用Init方法,这就是为什么我们将方法定义为私有和显式的IAccount。
4.由于new()约束,您应该为Account提供无参数构造函数。 如果您这样做,您的客户端代码不应该调用此无参数ctor。

至于我,我会按原样离开Activator.CreateInstance 。 对于genericsnew()约束的限制,这是一个很好的解决方法

这是我对该方法的通用性的看法。

 public abstract class BaseAccount { public string Notes; public virtual void Create() { ... } } public class Account : BaseAccount { ... } public class Account_Accessor : BaseAccount { ... } internal static void CreateAccount(out T account, bool saveToDatabase) where T : BaseAccount { DateTime created = DateTime.Now; string createdBy = _testUserName; account = (T)Activator.CreateInstance(typeof(T), new object[] { created, createdBy }); account.Notes = Utilities.RandomString(1000); if (saveToDatabase) account.Create(); } 

我假设Account和Account_Accessor足够相似,他们可以共享类似的类层次结构,或者可以实现相同的接口。 在这个例子中,我提供了一个抽象类,它们都是从中派生出来的,但是很容易用接口代替它。 但是,必须在两个类中完成全部实现。

知道了,我可以约束generics方法,以便T只是BaseAccount的子节点。 这样,我可以在不知道T的实际类型的情况下从该基类访问成员。