如果您需要在另一个项目中测试非公共属性,则使用Microsoft单元测试向导创建Accessor对象。在我的单元测试中,我创建了辅助函数,这样我就不会在每个单元测试方法中重复相同的代码。目前我有两个几乎相同的测试,除了一个采用标准对象,另一个采用Accessor版本。由于Accessor基于标准版本,我应该能够拥有一个功能,我认为我应该能够使用Generics来完成。问题是尝试重新输入和编译失败。
以下是现有的两个功能:
// 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<T>(out T account, bool saveToDatabase) {...}
但无法正确地重新计算帐户或帐户_Accessor。有什么建议?
答案 0 :(得分:3)
您应该为泛型函数添加约束,因为这两种方法:
account.Notes = Utilities.RandomString(1000);
account.Create();
我建议你用这两种方法添加一些接口,并将它的继承添加到你的两个类中。 约束应如下:
where T : YourNewInterface
关于约束,您可以在http://msdn.microsoft.com/en-us/library/bb384067.aspx上阅读
的更新强>
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<T>(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.我通过添加CreateInstance
约束来替换new()
2.由于.NET泛型限制因为new()约束不能有参数,我在Init()
接口添加了IAccount
方法。
3. Init
类的客户端代码不应该调用Account
方法,这就是为什么我们将方法定义为私有和显式为IAccount。
4.由于new()
约束,您应该为Account
提供无参数构造函数。如果您这样做,您的客户端代码不应该调用此无参数的ctor
至于我,我会按原样离开Activator.CreateInstance
。对于通用new()
约束
答案 1 :(得分:0)
这是我对该方法的通用性的看法。
public abstract class BaseAccount
{
public string Notes;
public virtual void Create() { ... }
}
public class Account : BaseAccount { ... }
public class Account_Accessor : BaseAccount { ... }
internal static void CreateAccount<T>(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足够相似,可以共享类似的类层次结构,或者可以实现相同的接口。在这个例子中,我提供了一个抽象类,它们都是从中派生出来的,但是用接口来实现它很容易。但是,必须在两个类中完成全部实现。
知道这一点,我可以约束泛型方法,以便T只是BaseAccount的子节点。这样,我可以在不知道T的实际类型的情况下从该基类访问成员。