0

Let's say we have a class that looks like this:

public class Repository<T>
{
    private readonly string _connectionString;

    public Repository(string connectionString)
    {
        _connectionString = connectionString;
    }

    void T SomeMethod()
    {
       // do work here
       return T;
    }
}

In the case above, the Type would need to be declared along with the class, but you would not need to specify the Type when calling SomeMethod().

Or, you could also do this:

public class Repository
{    
    private readonly string _connectionString;

    public Repository(string connectionString)
    {
        _connectionString = connectionString;
    }

    void T SomeMethod<T>()
    {
       // do work here
       return T;
    }
}

In this case, the class would be created without a Type, but you would need to declare the Type when calling SomeMethod().

Without a total duplication of all code, how would one create the same class so that the Type was optional when creating it? In other words, I'd like both of these to work upstream:

Repository<MyType> repo = new Repository<MyType>();
var something = repo.SomeMethod();

and

Repository repo = new Repository();
var something = repo.SomeMethod<MyType>();

Casey Crookston
  • 13,016
  • 24
  • 107
  • 193
  • 1
    Sounds like an XY problem... What real problem are you trying to solve? – Sweeper Mar 11 '20 at 21:54
  • Could you just share the same internal implementation inside the two separate interfaces? – Oliver Mar 11 '20 at 21:54
  • @Sweeper, nope. I asked exactly what I want to know. – Casey Crookston Mar 11 '20 at 21:55
  • @Oliver, that's the general idea I'm thinking too but I still can't see it in my head w/o a duplication of all code. – Casey Crookston Mar 11 '20 at 21:56
  • Repository can inherit from Repository or the other way around, if you dont want duplicate code. You can also use a runtime `Type t = null` optional parameter. – Charles Mar 11 '20 at 21:57
  • I don't think it's possible with C# https://stackoverflow.com/questions/707780/is-there-a-reasonable-approach-to-default-type-parameters-in-c-sharp-generics. – sipsorcery Mar 11 '20 at 22:02
  • Side-note: if you're using an ORM (like Entity Framework) then you do not need to use the Generic Repository (Anti-)Pattern (or rather: you **should not** use the Generic Repository (Anti-)Pattern because the ORM *is* the repository already, e.g. `DbSet`). – Dai Mar 11 '20 at 22:11
  • @Dia, using Dapper. – Casey Crookston Mar 11 '20 at 22:11
  • 1
    Is it your intention to create a generic repository for crud-like operations? Dapper.Contrib.Extensions already does that. – Robert Harvey Mar 11 '20 at 22:13

1 Answers1

4

If this is what you want to achieve, you could minimise duplication by wrapping the generic method implementation:

public class Repository
{
    public T SomeMethod<T>()
    {
        //Impl.
    }
}

public class Repository<T>
{
    private readonly Repository _base;

    public Repository()
    {
        _base = new Repository();
    }

    public T SomeMethod() => _base.SomeMethod<T>();
}

Where the generic class simply proxies through to the generic methods.

EDIT

Same concept as above, passing injected connectionString through to wrapped instance.

public class Repository
{
    private readonly string _connectionString;

    public Repository(string connectionString)
    {
        _connectionString = connectionString;
    }

    public T SomeMethod<T>()
    {
        //Impl.
    }
}

public class Repository<T>
{
    private readonly Repository _base;

    public Repository(string connectionString)
    {
        _base = new Repository(connectionString);
    }

    public T SomeMethod() => _base.SomeMethod<T>();
}
Oliver
  • 8,794
  • 2
  • 40
  • 60