正在转换对象或对象<;T>;到对象<;T、 T>;

本文关键字:对象 gt lt 转换 | 更新日期: 2023-09-27 18:29:34

我一直在关注Imar Spaanjars关于ASP.NET N层应用程序的博客,并了解ASP.NET Identity的代码实践。

我在继承和调用基方法方面遇到了一些麻烦。

信息

首先让我向您展示基本代码。基于Imar,我有一个CollectionBase类,我的所有列表类型属性都将从中继承。

public abstract class CollectionBase<T> : Collection<T>, IList<T> {
    protected CollectionBase() : base(new List<T>()) {}
    protected CollectionBase(IList<T> initialList) : base(initialList) {}
    protected CollectionBase(CollectionBase<T> initialList) : base(initialList) {}
    public void Sort(IComparer<T> comparer) {
        var list = (List<T>) Items;
        if (list != null) {
            list.Sort(comparer);
        }
    }
    public void Sort() {
        var list = (List<T>) Items;
        if (list != null) {
            list.Sort();
        }
    }
    public void AddRange(IEnumerable<T> collection) {
        if (collection == null) {
            throw new ArgumentNullException("collection", "Parameter collection is null.");
        }
        foreach (var item in collection) {
            Add(item);
        }
    }
}

然后,我有了另一个类,我想使用ASP.NET Identity的代码实践使其尽可能通用。

// this class is instantiated with 2 types, one for the Id property for emails and one for the Id property for owner
public class Emails<TKey, TOwner> : CollectionBase<Email<TKey, TOwner>> {
    public Emails() {}
    public Emails(IList<Email<TKey, TOwner>> initialList) : base(initialList) {}
    public Emails(CollectionBase<Email<TKey, TOwner>> initialList) : base(initialList) {}
}

我现在正试图创建一个从泛型继承的类作为快捷方式,类似于ASP.NET Identity的做法,它从泛型继承,具有假定的类型。

public class Emails : Emails<String, String> {
    public Emails() {}
    public Emails(IList<Email> initialList) : base(initialList) {
        // getting error on the 'base' call since there is no signature similar to Emails(IList<Email> initialList)
        // how can I convert the parameter IList<Email> initialList to an IList<Email<String, String>>
    }
    public Emails(CollectionBase<Email> initialList) : base(initialList) {
        // getting error on the 'base' call since there is no signature similar to Emails(CollectionBase<Email> initialList)
        // how can I convert the parameter CollectionBase<Email> initialList to a CollectionBase<Email<String, String>>
    }
}

以防万一,这里是Email

public class Email : Email<String> {
    public Email(String address, String ownerId)
        : base(address, ownerId) {}
}
public class Email<TKey> : Email<TKey, String> {
    public Email(String address, String ownerId)
        : base(address, ownerId) {}
}
public class Email<TKey, TOwner> : DomainEntity<TKey>, IHasOwner {
    public Email(String address, TOwner ownerId)
        : this() {
        Address = address;
        OwnerId = ownerId;
    }
    protected Email() {}
    public String Address { get; set; }
    public TOwner OwnerId { get; set; }
    public Person Owner { get; set; }
}

问题

正如我在评论中所指出的,我遇到的问题是基类没有Emails(IList<Email> initialList)Emails(CollectionBase<Email> initialList)的签名方法,当然它们也不应该有。我知道我不应该像上面那样调用base,但我把它留在了那里,以防有一个非常简单的代码可以在可以调用的地方进行转换,而不必在方法中编写额外的代码。

问题

如何将参数类型IList<Email> initialListCollectionBase<Email> initialList分别"转换"为List<Email<String, String>>CollectionBase<Email<String, String>>

潜在答案

我可能自己创造了答案,但我还不够熟悉,不知道这是怎么做的。如果不是,请提供我应该做的任何更改和/或提供一个完全不同的答案。

这是我玩了一会儿之后的课。

public class Emails : Emails<String, String> {
    public Emails() {}
    public Emails(IList<Email> initialList) : base((IList<Email<String, String>>)initialList.Select(email => new Email<String, String>(email.Address, email.OwnerId))) {}
    public Emails(CollectionBase<Email> initialList) : base((CollectionBase<Email<String, String>>)initialList.Select(email => new Email<String, String>(email.Address, email.OwnerId))) {}
}

正在转换对象或对象<;T>;到对象<;T、 T>;

您可以做一个扩展方法来实现强制转换吗。无法执行隐式强制转换,因为编译器不知道如何将Generics.List转换为Generics.List.

要解决您的问题,请尝试:

我将方法更改为调用基类中的方法。

public class Emails : Emails<String, String>
{
    public Emails()
    {
    }
    public Emails(IList<Email> initialList) : base(initialList.ToMyList())
    {
        // getting error on the 'base' call since there is no signature similar to Emails(IList<Email> initialList)
        // how can I convert the parameter IList<Email> initialList to an IList<Email<String, String>>
    }
    public Emails(CollectionBase<Email> initialList) : base(initialList.ToMyCollection())
    {
        // getting error on the 'base' call since there is no signature similar to Emails(CollectionBase<Email> initialList)
        // how can I convert the parameter CollectionBase<Email> initialList to a CollectionBase<Email<String, String>>
    }
}

我用一个扩展方法来转换你的类:

public static class ExtensionListEmail
{
    public static IList<Email<string, string>> ToMyList(this IList<Email> list)
    {
        return new List<Email<string, string>>(list);
    }
    public static CollectionBase<Email<string, string>> ToMyCollection(this CollectionBase<Email> collection)
    {
        return new Emails(collection);
    }
}

我希望我帮过忙。

在我看来,没有必要创建Emails快捷方式。实现Emails快捷方式如下:

public class StringList : List<string>
{
}

这意味着为了使用List对象,我们为它创建了一个专用的类。但实际上,我们大多数时候并没有这样做。我们所做的如下:

var stringList = new List<string>();

所以,如果您废弃了Emails快捷方式,您就不会有问题了。此外,你可以使用所有其他类如下:

var emails = new Emails<string, string>();
emails.Add(new Email("key", "ownerId"));

当然,实现这一点的前提是Emails类只是一条捷径。如果您需要在该类中实现一些特定的函数,这些函数对应于它使用的泛型类型,那就另当别论了。

到目前为止,这是我正在使用的解决方案,直到有人能够使Gibran Silvia的答案对这两个函数都更通用。

public class Emails : Emails<String, String> {
    public Emails() {}
    public Emails(IList<Email> initialList) : base((IList<Email<String, String>>) initialList.Select(email => new Email<String, String>(email.Address, email.OwnerId))) {}
    public Emails(CollectionBase<Email> initialList) : base((CollectionBase<Email<String, String>>) initialList.Select(email => new Email<String, String>(email.Address, email.OwnerId))) {}
}