在 C# 中,如何创建需要访问多个列表类型的可重用方法?

In C#, how can I create a reusable method where I need to access multiple list types?

我有以下两种方法:

private void AddHeaderAttachment(AAttachment attachment) {
    string parentId = attachment.ParentId;
    if (this.collectionByIds.TryGetValue(attachment.Id, out MyCollection collection)) {
        if (!collection.AAttachmentByParentIds.TryGetValue(parentId, out List<AAttachment> attachmentList)) {
            attachmentList = new List<AAttachment>();
            collection.AAttachmentByParentIds.Add(parentId, attachmentList);
        }
        attachmentList.Add(attachment);
    }
}

private void AddLineAttachment(BAttachment attachment) {
    string parentId = attachment.ParentId;
    if (this.collectionByIds.TryGetValue(attachment.Id, out MyCollection collection)) {
        if (!collection.BAttachmentByParentIds.TryGetValue(parentId, out List<BAttachment> attachmentList)) {
            attachmentList = new List<BAttachment>();
            collection.BAttachmentByParentIds.Add(parentId, attachmentList);
        }
        attachmentList.Add(attachment);
    }
}

class MyCollection 看起来像这样:

 public class MyCollection {
        public Dictionary<string, List<AAttachment>> AAttachmentByParentIds = new Dictionary<string, List<AAttachment>>();
        public Dictionary<string, List<BAttachment>> BAttachmentByParentIds = new Dictionary<string, List<BAttachment>>();
}

如您所见,上述两种方法之间的唯一区别是:

  1. 提供的类型
  2. MyCollection 的 属性 其中 附件将被添加到。

但是,AAttachmentBAttachment 都实现了:

 interface Attachable {
    string ParentId { get; }
 }

我想创建一个可重复使用的方法。

但是我有两个明显的问题:

  1. 如果我将内部 if 更改为:
                if (!collection.AAttachmentByParentIds.TryGetValue(parentId, out List<Attachable> attachmentList)) {
                    attachmentList = new List<Attachable>();
                    collection.lineAttachmentByParentIds.Add(parentId, attachmentList);
                }

Visual Studio 通知我“参数 2:无法将 out List<Attachable> 转换为 out List<AttachmentA>

  1. 如何更改我在 MyCollection 实例上引用的是 AAttachmentByParentIds 还是 BAttachmentByParentIds

您是否尝试过使用 generics :

private void AddAttachable<T>(....) where T:Attachable 

完整代码如下所示:

private void AddAttachable<T>(T attachment, Func<MyCollection, Dictionary<string,T>> getFunc) 
     where T:Attachable  
{
string parentId = attachment.ParentId;
if (this.collectionByIds.TryGetValue(attachment.Id, out MyCollection collection)) {
    // func is used here
    if (!getFunc(collection).TryGetValue(parentId, out List<T> attachmentList)) {
        attachmentList = new List<T>();
        // and here, can be moved to variable
        getFunc(collection).Add(parentId, attachmentList);
    }
    attachmentList.Add(attachment);
}
}

和用法

BAttachment bAttach = ...
AddAttachment(bAttach, col => col.BAttachmentByParentIds )

您想使用泛型:

private void AddHeaderAttachment<TAttachment>(
    Func<MyCollection, Dictionary<string, List<TAttachment>>> attachmentByParentIdsSelector,
    TAttachment attachment) where TAttachment : Attachable
{
    string parentId = attachment.ParentId;
    if (this.collectionByIds.TryGetValue(attachment.Id, out MyCollection collection))
    {
        var attachmentByParentIds = attachmentByParentIdsSelector(collection);
        if (!attachmentByParentIds.TryGetValue(parentId, out List<TAttachment> attachmentList))
        {
            attachmentList = new List<TAttachment>();
            attachmentByParentIds.Add(parentId, attachmentList);
        }
        attachmentList.Add(attachment);
    }
}

private void AddHeaderAttachment(AAttachment attachment) 
{
    AddHeaderAttachment(x => x.AAttachmentByParentIds, attachment);
}

private void AddHeaderAttachment(BAttachment attachment) 
{
    AddHeaderAttachment(x => x.BAttachmentByParentIds, attachment);
}