将对象或对象<t>转换为对象<t,t =“”>

时间:2016-01-09 18:25:05

标签: c# generics inheritance type-conversion

我一直关注Imar Spaanjaars关于ASP.NET N-Layered Applications的博客以及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)的签名方法,当然它们不应该有。{1}}和base。我知道我不应该像上面那样调用IList<Email> initialList,但我把它留在那里,以防有一个非常简单的代码来进行可以调用的转换,而不必在其中编写额外的代码方法

问题

如何将参数类型CollectionBase<Email> initialListList<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))) {} }

潜在答案

我可能已经自己创造了答案,但我不熟悉,知道这是做到这一点的方法。如果不是,请提供我应该做的任何更改和/或提供完全不同的答案。

在我玩了一下后,这是我的课。

{
  "id": {
    "S": "1eb4520d44715b6daa5f9d907fe43aab" //md5sum of "time"
  },
  "message": {
    "S": "I'm creating the audible reporting log now."
  },
  "status": {
    "S": "working"
  },
  "time": {
    "S": "1452297505" //timestamp: should probably add milliseconds for sake of unique "id"
  }
}

3 个答案:

答案 0 :(得分:1)

你可以做一个扩展方法来实现一个强制转换。 无法进行隐式转换,因为编译器不知道如何将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);
    }
}

我希望我帮助过。

答案 1 :(得分:0)

在我看来,没有必要创建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类只是一个捷径。如果你需要在该类中实现一些与它使用的泛型类型相对应的特定函数,那就是另一个故事。

答案 2 :(得分:0)

截至目前,这是我正在使用的解决方案,直到有人可以使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))) {}
}
相关问题