Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper way a implementing property based on generic type

I have the following interface

public interface IRepository<T> where T : IEntity, new()
{
    List<T> GetAll();
}

which i implemented here

public abstract partial class WhsePricingRatesAddOnProviderBase : WhsePricingRatesAddOnProviderBaseCore, IRepository<WhsePricingRatesAddOn>
{
    /// <summary>
    /// Gets all rows from the DataSource.
    /// </summary>
    /// <returns>Returns a TList of Entity objects.</returns>
    public override List<WhsePricingRatesAddOn> GetAll()
    {
        return base.GetAll();
    }
}

AND ALSO HERE

which i implemented here

public abstract partial class WhsePricingRatesAddOn2ProviderBase : WhsePricingRatesAddOn2ProviderBaseCore, IRepository<WhsePricingRatesAddOn2>
{
    /// <summary>
    /// Gets all rows from the DataSource.
    /// </summary>
    /// <returns>Returns a TList of Entity objects.</returns>
    public override List<WhsePricingRatesAddOn2> GetAll()
    {
        return base.GetAll();
    }
}

When I try to use it in a class

 public class TypeRate
    {
        public IRepository Repository { get; set; }

        public TypeRate(int i)
        {
    if (i == 1)
            {
                Repository = (IRepository<WhsePricingRatesAddOn>)SCMSDevMaster.Data.DataRepository.WhsePricingRatesAddOnProvider;}
    else
            {
                Repository = (IRepository<WhsePricingRatesAddOn2>)SCMSDevMaster.Data.DataRepository.WhsePricingRatesAddOn2Provider;}
            }
        }
    }

I either get this error if i dont put <T> after the IRepository declaration

Using the generic type 'IRepository<T>' requires one argument.

or if i put it, then i get

The type of namespace name 'T' could not be found error

I want my TypeRate class to be unaware of T until it's runtime creation, at which point i will set with code the proper T for the repository.

am I looking at this the wrong way ?

I should point out the SCMSDevMaster.Data.DataRepository.WhsePricingRatesAddOnProvider is static;

like image 464
SerenityNow Avatar asked Mar 13 '26 16:03

SerenityNow


2 Answers

The problem is your Repository property declaration - you just need to specify the type argument, which you can do directly given that you've only got one type which will work, by the looks of it:

public IRepository<WhsePricingRatesAddOn> Repository { get; set; } 

I don't understand why you say you want TypeRate to be unaware of the type of T, as it's clearly set in the constructor...

You could make TypeRate generic too (i.e. make it TypeRate<T> and declare your property as IRepository<T>), but then the constructor body wouldn't compile, as it's explicitly casting to IRepository<WhsePricingRatesAddOn>.

It's possible that you could introduce a non-generic IRepository interface as a super-interface of IRepository<T> - but you've already got IEntity, and all you're adding is the GetAll() method which relies on T...

Fundamentally, I think you really need to decide what information is known at compile-time and what information is only known at execution-time - because it sounds like you have inconsistent requirements at the moment.

like image 98
Jon Skeet Avatar answered Mar 16 '26 05:03

Jon Skeet


This definition

public IRepository Repository { get; set; } 

is not complete, because there isn't a class (or interface) called IRepository. There is a generic interface with one type parameter called IRepository, but that's another thing.

Declare the Repository with the concrete specified type, like this:

public IRepository<WhsePricingRatesAddOn> Repository { get; set; } 

On the other hand, if you need the type of the repository to differ, the problem will be the line:

SCMSDevMaster.Data.DataRepository.WhsePricingRatesAddOnProvider

Which is as specific as it can get. I don't see how you can make that part dynamic without major redesigns, and I do not have enough info about your design to offer further advice.

like image 45
SWeko Avatar answered Mar 16 '26 04:03

SWeko



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!