Fixer
Fixer

Reputation: 6095

Unable to infer generic type from a collection

Why is it not possible to do this:

public static void Init<TEntity>(params TEntity[] repositories) where TEntity : Entity
{
    foreach (TEntity item in repositories)
    {
       Repository<item> rep = new Repository<item>();
    }
}

The above code won't compile: Cannot resolve symbol item

Yet this works:

public static void Init<TEntity>(TEntity entity) where TEntity : Entity
{
    Repository<TEntity> rep = new Repository<TEntity>();
}

EDIT

I'm editing the OP to give a bigger picture of the problem. We are experiencing some issues with the entity framework Db Context being spawned by multiple repositories. Currently we access the repositories like:

Repository<Product> rep = new Repository<Product>()
Repository<Account> rep = new Repository<Account>()

Since there's a relationship between product and account EF will complain about objects being attached to a different context. So we are trying to resolve this issue by consolidating repository access into a Unit of Work pattern:

Here's an example of what I'm trying to achieve:

public class UnitOfWork
{
    protected List<Entity> Repositories = new List<Entity>();
    private readonly DbContext _context;
    protected UnitOfWork()
    {
       _context = new SqlDbContext();
    }

    public static UnitOfWork Init<TEntity>(params TEntity[] repositories) where TEntity : Entity
    {
            UnitOfWork uow = new UnitOfWork();
        foreach (TEntity item in repositories)
        {
            Repository<item> rep = new Repository<item>();
            uow.Repositories.Add(rep);
        }
            return uow;
    }

    public IRepository<T> GetRepository<T>() where T : Entity
    {
        return Repositories.OfType<T>().Single();
    }   
}

So we can access our repositories like:

GetRepository<Product>().GetById(1);
GetRepository<Account>().GetById(123434);

Upvotes: 1

Views: 305

Answers (4)

armen.shimoon
armen.shimoon

Reputation: 6401

    public static UnitOfWork Init<T1>()
    {
        UnitOfWork uow = new UnitOfWork();
        uow.Add(new Repository<T1>());
        return uow;
    }

    public static UnitOfWork Init<T1,T2>()
    {
        UnitOfWork uow = Init<T1>();
        uow.Add(new Repository<T2>());
        return uow;
    }

    public static UnitOfWork Init<T1, T2, T3>()
    {
        UnitOfWork uow = Init<T1,T2>();
        uow.Add(new Repository<T3>());
        return uow;
    }

    // ...

Upvotes: 1

Manish Basantani
Manish Basantani

Reputation: 17509

Not sure what makes you try the first case ( Repository<item> rep = new Repository<item>(); ). Here, 'item' is an instance and not a type. If you need a genertic item your second case does it best.

Please elaborate your 'problem'.

Edit: If this question is out of curiosity, then you may take a look at 'MakeGenericType) method, following code explains the usage.

       Type generic = typeof(Repository<>);

       Type[] typeArgs = { item.GetType() };

       Type constructed = generic.MakeGenericType(typeArgs);
// This will create Repository<item> type.

Upvotes: 2

BrokenGlass
BrokenGlass

Reputation: 161002

item is an instance of a type, but you need a type parameter to create an instance of your generic Repository<T> class.

Upvotes: 4

Jason
Jason

Reputation: 15931

That's incorrect syntax. Item is an instance of type TEntity. You don't use instance variables with generic definitions.

Upvotes: 0

Related Questions