You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何强制Activator创建的实例调用子类的Shadowed Add方法?

问题与解决方案

问题描述

我定义了继承自ObservableCollection<MyClassItem>的CustomCollection类,使用new关键字隐藏Add方法并添加自定义逻辑:

class MyClassItem
{
    ...
}

class CustomCollection : ObservableCollection<MyClassItem>
{
    public CustomCollection(){}
    public new void Add(MyClassItem item)
    {
       //...自定义处理逻辑
       base.Add(item);
    }
}

同时实现了泛型复选列表类MyGenericCheckList<T>,其GetSelectedItemsAsCollection<CT>方法通过Activator.CreateInstance<CT>创建指定类型的集合,并添加选中项:

class GenericCheckListItem<T>
{
   //...自定义实现
   public T Item {get; set;}
}

class MyGenericCheckList<T> : ObservableCollection<GenericCheckListItem<T>>
{
    //...自定义实现
    
    public CT GetSelectedItemsAsCollection<CT>() where CT: ICollection<T>, new()
    {
        CT collection = Activator.CreateInstance<CT>();
        foreach(var item in this)
        {
            collection.Add(item.Item);
        }
        return collection;
    }
}

使用示例:

MyGenericCheckList<MyClassItem> cList = new MyGenericCheckList<MyClassItem>();
// ...添加数据并选择项目
var myColl = cList.GetSelectedItemsAsCollection<CustomCollection>();

问题:尽管collection实例是CustomCollection类型,但调用的Add方法是基类ObservableCollection的实现,而非自定义的隐藏方法,导致自定义的簿记逻辑未执行。请问如何强制调用该自定义方法?若不可行,有其他实现思路吗?

解决思路

1. 类型转换调用(局限性大)

在GetSelectedItemsAsCollection方法中,判断创建的集合是否为CustomCollection类型,若是则转换为该类型后调用其Add方法,否则使用接口的Add。但这种方式会让方法与CustomCollection强耦合,失去泛型的通用性:

public CT GetSelectedItemsAsCollection<CT>() where CT: ICollection<T>, new()
{
    CT collection = Activator.CreateInstance<CT>();
    if (collection is CustomCollection customColl)
    {
        foreach(var item in this)
        {
            customColl.Add(item.Item);
        }
    }
    else
    {
        foreach(var item in this)
        {
            collection.Add(item.Item);
        }
    }
    return collection;
}

2. 重写ObservableCollection核心方法(推荐)

ObservableCollection<T>的Add方法最终会调用InsertItem虚方法,因此不要用new隐藏Add,而是重写InsertItem来注入自定义逻辑。这样无论通过子类Add、基类Add还是ICollection<T>接口调用Add,都会触发自定义逻辑:

class CustomCollection : ObservableCollection<MyClassItem>
{
    public CustomCollection(){}
    
    protected override void InsertItem(int index, MyClassItem item)
    {
        //...自定义处理逻辑
        base.InsertItem(index, item);
    }
}

这种方式符合ObservableCollection的设计规范,避免了方法隐藏带来的调用歧义问题。

3. 自定义接口+泛型约束

如果一定要保留new的Add方法,可以定义包含自定义Add的接口,让CustomCollection实现它,再修改泛型方法的约束,直接调用自定义Add:

public interface ICustomAdd<T>
{
    void Add(T item);
}

class CustomCollection : ObservableCollection<MyClassItem>, ICustomAdd<MyClassItem>
{
    public CustomCollection(){}
    
    public new void Add(MyClassItem item)
    {
        //...自定义处理逻辑
        base.Add(item);
    }
}

// 修改泛型方法约束
public CT GetSelectedItemsAsCollection<CT>() where CT: ICollection<T>, ICustomAdd<T>, new()
{
    CT collection = Activator.CreateInstance<CT>();
    foreach(var item in this)
    {
        collection.Add(item.Item);
    }
    return collection;
}

但这种方式要求所有目标集合类型都实现ICustomAdd<T>接口,通用性不如第二种方案。


内容的提问来源于stack exchange,提问作者Kikanye

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 23:25:21