创建一个从ToDictionary()派生的扩展方法

时间:2019-08-23 10:08:34

标签: c# dictionary extension-methods

我想创建一个从ToDictionary()派生的扩展方法。目前,为了达到期望的结果,我这样做:

ObjectAttributes = model.ObjectAttributes.ToDictionary(
    oa => oa.Attribute.Name, oa => oa.ToWrapper<ObjectAttributeWrapper>());

所以我使用以下ToDictionary签名:

public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement>(
    this IEnumerable<TSource> source,
    Func<TSource, TKey> keySelector,
    Func<TSource, TElement> elementSelector);

我想知道是否可以这样做?

ObjectAttributes = model.ObjectAttributes.ToDictionaryWrapper<ObjectAttributeWrapper>(
    oa => oa.Attribute.Name);

这是当前的实现,但是显然不能正常工作

public static Dictionary<TKey, TWrapper> ToDictionaryWrapper<TWrapper, TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) where TSource : BaseModel where TWrapper : IBaseWrapper
{
        return source.ToDictionary(keySelector, model => model.ToWrapper<TWrapper>());
}

编辑: ToWrapper()的实现:

public static TWrapper ToWrapper<TWrapper>(this BaseModel model) where TWrapper : IBaseWrapper
    {
        if (model == null)
            return default;

        var type = typeof(TWrapper);

        if (_wrapperParents.ContainsKey(type) && _wrapperParents[type].Id == model.Id)
            return (TWrapper)_wrapperParents[type];
        else
            return (TWrapper)GetConstructor<TWrapper>().Invoke(new object[] { model });
    }

    public static IEnumerable<TWrapper> ToListWrapper<TWrapper>(this IEnumerable models) where TWrapper : IBaseWrapper
    {
        var _models = models as IEnumerable<BaseModel>;
        if (_models == null)
            return default;

        return _models.Select(model => model.ToWrapper<TWrapper>());
    }

1 个答案:

答案 0 :(得分:0)

通常,对于单个通用约束列表,您只能显式提供所有自变量,或者使所有自变量自动解析。您不能部分提供约束。

因此,您的选择如下(我假设TWrapper将具有属性WrappedObject

  • 按原样提供所有参数
  • 减少通用参数的数量(如果键类型始终相同,您甚至可以使键类型成为非通用类型)
// signature
Dictionary<TKey, TWrapper> ToDictionaryWrapper<TWrapper, TKey>(
    this IEnumerable<BaseModel> source,
    Func<BaseModel, TKey> keySelector)
    where TWrapper : IBaseWrapper;
// call
model.ObjectAttributes
    .ToDictionaryWrapper<ObjectAttributeWrapper, string>(oa => oa.Attribute.Name);
  • 将函数调用分为两部分,其中一部分是显式的,另一部分是隐式的
// signature
IEnumerable<TWrapper> Wrap<TWrapper>(this IEnumerable<BaseModel> source)
    where TWrapper : IBaseWrapper;

Dictionary<TKey, TWrapper> ToDictionaryWrapper<TWrapper, TKey>(
    this IEnumerable<TWrapper> source,
    Func<BaseModel, TKey> keySelector)
    where TWrapper : IBaseWrapper;
// call
model.ObjectAttributes
    .Wrap<ObjectAttributeWrapper>()
    .ToDictionaryWrapper(oa => oa.Attribute.Name);
  • 不必担心自定义ToDictionaryWrapper,只需使用Wrap-Function和框架ToDictionary
// call (signature for Wrap same as above)
model.ObjectAttributes
    .Wrap<ObjectAttributeWrapper>()
    .ToDictionary(w => w.WrappedObject.Attribute.Name);