有没有一种方法可以根据其类型在类中查找集合?

时间:2018-06-22 16:59:51

标签: c# .net generics types

我认为EF的DBContextDBSets是此问题的背景。例如,您可以使用Repository类中的以下代码访问特定集合。

public TEntity Get(int id)
{
    return Context.Set<TEntity>().Find(id);
}

Set<TEntity>()返回TEntity类型的集合。编码方式如何?我试图找到它的源代码无济于事。我需要创建自己的类并完整写出逻辑吗?

3 个答案:

答案 0 :(得分:1)

我猜测Enumerable.OfType<TResult>()在这里会派上用场。它在源枚举中的类型IEnumerable<TResult>的所有元素上返回TResult。至于其实现,MSDN表示:

  

此方法通过使用延迟执行来实现。立即返回值是一个对象,该对象存储执行操作所需的所有信息。在通过直接调用其GetEnumerator方法或在Visual C#中使用foreach或在Visual Basic中使用For Each枚举该对象之前,不会执行此方法表示的查询。

答案 1 :(得分:1)

我不知道EF是如何做到的,但是您可以轻松地用Types键的Dictionary完成类似的事情

private Dictionary<Type, ICollection> registry = new Dictionary<Type, ICollection>();

// adds a collection of a certain type
public void Add<T>(T collection) where T: ICollection {
    registry.Add(typeof(T), collection);
}

// create an empty collection of type T and add it to registry
public void InitCollection<T>() where T: ICollection { 
    registry.Add(typeof(T), (ICollection)Activator.CreateInstance(typeof(T)));
}

// returns a collection of type T if it has been registered
public T Set<T>() where T: ICollection {
    return (T)registry[typeof(T)];
}

答案 2 :(得分:1)

TLDR :EF仅在关键字为DbSet<T>的字典中创建一个typeof(T)条目。


看看sourcecode,它的实现方式如下:

/// <summary>
///     Creates a <see cref="DbSet{TEntity}" /> that can be used to query and save instances of <typeparamref name="TEntity" />.
/// </summary>
/// <typeparam name="TEntity"> The type of entity for which a set should be returned. </typeparam>
/// <returns> A set for the given entity type. </returns>
public virtual DbSet<TEntity> Set<TEntity>()
    where TEntity : class
    => (DbSet<TEntity>)((IDbSetCache)this).GetOrAddSet(DbContextDependencies.SetSource, typeof(TEntity));

还有Line 195

/// <summary>
///     This API supports the Entity Framework Core infrastructure and is not intended to be used
///     directly from your code. This API may change or be removed in future releases.
/// </summary>
object IDbSetCache.GetOrAddSet(IDbSetSource source, Type type)
{
    CheckDisposed();

    if (!_sets.TryGetValue(type, out var set))
    {
        set = source.Create(this, type);
        _sets[type] = set;
    }

    return set;
}

sets is处:

private readonly IDictionary<Type, object> _sets = new Dictionary<Type, object>();