更新使用泛型的两个常用功能常用、两个、功能

2023-09-03 06:15:22 作者:迟来的心痛〃

使用微软单元测试向导,它会创建如果你需要在另外一个项目来测试一个非公开的属性存取对象。在我的单元测试创​​建的辅助功能,因此,我不重复同样的code只是在每一个单元测试方法。目前我有两个测试,是几乎相同的除了一个需要一个标准的对象,以及其他需要访问器版本。由于访问器是基于标准的版本,我应该能有一个功能,我想我应该可以使用泛型来完成。这个问题正试图重新输入和编译失败。

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 that I don't repeat the same code just in every Unit Test method. Currently I have two tests that are almost identical except one takes a standard object, and the other takes the Accessor version. Since the Accessor is based on the standard version I should be able to have one function and I assume I should be able to use Generics to accomplish. The issue is trying to retype and compile failures.

下面是现有的两个功能:

Here are the existing two functions:

// 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();
}

我试图改变签名的组合功能为:

I tried changing the signature to of a combined function to:

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

但无法得到重铸牛逼妥善帐户或Account_Accessor。有什么建议么?

but couldn't get recast T properly to Account or Account_Accessor. Any suggestions?

推荐答案

您应该增加,因为这两个方法的限制的通用功能,:

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

关于约束,你可以阅读 http://msdn.microsoft.com/ EN-US /库/ 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 加入新()的约束。 2.因为new()约束不能有,因为.NET泛型的限制参数,我已经添加了的init()方法将 IAccount 接口。 3. 初始化方法不应由帐户类的客户端code被调用,这就是为什么我们定义方法为私有的,明确的IAccount。 4.因为新()约束应为帐户提供参数的构造函数。如果你这样做,你的客户端code不应该使用这个参数的构造函数。 至于我,我会离开 Activator.CreateInstance 原样。这是很好的办法解决通用的限制新()约束

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