将通用List <t>作为委托参数传递</t>

时间:2015-01-09 08:32:56

标签: c# events generics type-conversion

我编写了一个事件,用于将带有类型(T)的通用项的List传递给所有订阅者:

public delegate void GenericListItemCountChangedEvent(List<Object> sender, GenericListItemCountChangedEventArgs e);
public event GenericListItemCountChangedEvent GenericListItemCountChanged;

private void RaiseGenericListItemCountChanged<T>(List<T> List) where T : BaseElem {
    if (GenericListItemCountChanged != null)
        GenericListItemCountChanged(List as List<Object>, new GenericListItemCountChangedEventArgs(typeof(T)));
}

这是一个类的声明,它订阅了上面的事件:

 _catalog.GenericListItemCountChanged += (sender, e) => GenericListItemCountChanged(sender, e);

这是事件转发到订阅者内部的方法:

private void GenericListItemCountChanged(List<Object> sender, Catalog.GenericListItemCountChangedEventArgs e) {
    Catalog.ListTypes changedListType = Catalog.GetListTypeFromList(changedList); 
    //GetListTypeFromList expects parameter to be a type of <T> where T : BaseElem
}

显然,List<Object>无法转换为List<T> where T : BaseElem

如果您能提供一个解决方案来检索列表中包含他们&#34;真实&#34;的项目,我会接受您的回答。在方法内部输入,处理事件。
(恢复原始列表状态)

&#34;真实&#34;列表中的项目类型存储在EventArgs中。
但我不知道这是否可以帮助我...

SOLUTION:
没有@ChrFin的帮助,我无法理解这一点,感谢队友!

公共类目录:对象

public delegate void GenericListItemCountChangedEvent(IEnumerable<BaseElem> sender, GenericListItemCountChangedEventArgs e);
public event GenericListItemCountChangedEvent GenericListItemCountChanged;

private void RaiseGenericListItemCountChangedEvent<T>(List<T> List) where T : BaseElem {
    if (GenericListItemCountChanged != null) {
        GenericListItemCountChanged(List, new GenericListItemCountChangedEventArgs());
    }
}
public void ForceRaiseGenericListItemCountChangedEvent<T>(List<T> List) where T : BaseElem {
    RaiseGenericListItemCountChangedEvent(List);
}

public class GenericListItemCountChangedEventArgs {
    public GenericListItemCountChangedEventArgs() {
    }
}

-

    public static ListTypes GetListTypeFromList<T>(IEnumerable<T> List) where T : BaseElem {
        Type typeofT = List.GetType().GetGenericArguments()[0];
        //typeofT now contains correct subtype of 'BaseElem'
        return ListTypes.SomeType //based on 'typeOfT'
    }

公共部分类MainWindow:Window

    _catalog.GenericListItemCountChanged += (sender, e) => GenericListItemCountChanged(sender, e);

-

private void GenericListItemCountChanged(IEnumerable<BaseElem> sender, Catalog.GenericListItemCountChangedEventArgs e) {
            Catalog.ListTypes changedListType = Catalog.GetListTypeFromList(sender);
            //We now know the changed ListType
}

非常感谢!

1 个答案:

答案 0 :(得分:1)

有两种解决方法:Covariance和泛型:

1)泛型:
您还需要创建一个通用委托:

public class YourClass<T> where T : BaseElem
{
    public delegate void GenericListItemCountChangedEvent<T>(List<T> sender,
                             GenericListItemCountChangedEventArgs e);
    public event GenericListItemCountChangedEvent<T> GenericListItemCountChanged;

    private void RaiseGenericListItemCountChanged<T>(List<T> List)
    {
        if (GenericListItemCountChanged != null)
        {
            GenericListItemCountChanged(List,
               new GenericListItemCountChangedEventArgs(typeof(T)));
        }
    }
}

当然,在这种情况下,您只能使用一种显式类型的基类型BaseElem

2)协方差:
使用IEnumerable<T>接口而不是显式类型来支持协方差:

public delegate void GenericListItemCountChangedEvent(IEnumerable<BaseElem> sender,
                         GenericListItemCountChangedEventArgs e);
public event GenericListItemCountChangedEvent GenericListItemCountChanged;

private void RaiseGenericListItemCountChanged(IEnumerable<BaseElem> List)
{
    if (GenericListItemCountChanged != null)
    {
        var itemType = List.Count() > 0 ? List.First().GetType() : typeof(BaseElem);
        GenericListItemCountChanged(List,
            new GenericListItemCountChangedEventArgs(itemType));
    }
}

3)丑陋,但会奏效:施法:

public delegate void GenericListItemCountChangedEvent(List<BaseElem> sender,
                         GenericListItemCountChangedEventArgs e);
public event GenericListItemCountChangedEvent GenericListItemCountChanged;

private void RaiseGenericListItemCountChanged<T>(List<T> List) where T : BaseElem
{
    if (GenericListItemCountChanged != null)
    {
        GenericListItemCountChanged(List.Cast<BaseElem>().ToList(),
            new GenericListItemCountChangedEventArgs(typeof(T)));
    }
}