Reputation: 11
I'm trying to pass in a dynamic model class to a more generic class. Part of the generic class is using dapper querying to a typed List. I'm trying to make this generic class modular in that in can take in any model class and be able to use this model class as an output of the query.
Am I even approaching this problem in the right way?
So in the example below, I'd like for the GetFruits
method to be dynamic in that it would return List<Bananas>
if Bananas
is passed in or List<Orange>
if Oranges
is passed in
class FruitBasket
{
public FruitBasket(dynamic ModelClass)
{
}
public List<Orange> GetFruits(connection)
{
List<Orange> oranges = connection.Query<Orange>("Select * from Oranges");
return oranges
}
}
//Passes in Oranges model class
var fruits = new FruitBasket(new Oranges())
//Passes in Bananas model class
var fruits = new FruitBasket(new Bananas ())
Upvotes: 1
Views: 86
Reputation: 28737
You can either make the class generic or you can make the method generic. Either way, you need a base class for your different fruits:
public class Fruit { }
public class Orange : Fruit { }
public class Banana : Fruit { }
Generic class approach:
public class FruitBasket<T> Where T : Fruit // FruitBasket of something where something must be a fruit
{
public List<T> GetFruits(connection)
{
var fruitType = typeof(T);
if (fruitType == typeof(Banana))
return connection.Query<Banana>("Select * from Bananas");
else if (fruitType == typeof(Orange))
return connection.Query<Orange>("Select * from Oranges");
}
}
var orangeBasket = new FruitBasket<Orange>();
var oranges = orangeBasket.GetFruits(connection);
var bananaBasket = new FruitBasket<Banana>();
var bananas = bananaBasket.GetFruits(connection);
Generic method approach:
public class FruitBasket
{
public List<T> GetFruits<T>(connection Where T : Fruit // Get list of something where something must be a fruit
{
var fruitType = typeof(T);
if (fruitType == typeof(Banana))
return connection.Query<Banana>("Select * from Bananas");
else if (fruitType == typeof(Orange))
return connection.Query<Orange>("Select * from Oranges");
}
}
var fruitBasket= new FruitBasket();
var oranges = fruitBasket.GetFruits<Orange>(connection);
var bananas = fruitBasket.GetFruits<Banana>(connection);
Which approach you choose depends on your use case. Can a fruit basket only contain one type of fruit? => generic class Can a fruit basket contain multiple types of fruit? => generic method
Upvotes: 0
Reputation: 41
Here is how GetFruits
should look like
public List<Fruit> GetFruits(connection)
{
if (FruitBasket.CurrentFruit is Banana))
{
var bananas = connection.Query<Banana>("Select * from Bananas");
return bananas;
}
else if (FruitBasket.CurrentFruit is Orange)
{
var oranges = connection.Query<Orange>("Select * from Oranges");
return oranges;
}
//You may replace this exception by returning null or an empty list
throw new Exception("Not supported fruit type");
}
Another solution would be instead of using dynamic you may use fruite as a base class (or abstract class) for both orange and banana
Upvotes: 0
Reputation: 421
To accomplish your specific, literal request, I would approach this not with dynamic
, but with an IFruit
interface containing a GetFruits
method. Make your repository/list class accept a generic that must support that interface. Then it's just a matter of new MyRepoList<Banana>
. I would abandon dynamic
entirely as soon as possible - in my experience the short-term benefits never outweigh the long-term problems.
Generally - it sounds like you're working on a generic, simple repository. A general limitation of this approach (one entity per repository) is that at some point you're going to want to update multiple entities in one transaction. I would strongly encourage you to design your repositories around the units of work that your application actually performs, rather than trying to simplify/generalize how your entities are stored. It's far too easy to make your business logic awkward/difficult because you create the repositories first.
Upvotes: 0
Reputation: 10393
I'm guessing Banana
and Orange
are subclasses of Fruit
. So are you looking for something like this:
public class FruitBasket
{
public Fruit CurrentFruit { get; set; }
public FruitBasket(Fruit fruit)
{
CurrentFruit = fruit;
}
public List<Fruit> GetFruits(connection)
{
var fruitType = CurrentFruit.GetType();
if (fruitType == typeof(Banana))
{
var bananas = connection.Query<Banana>("Select * from Bananas");
return bananas;
}
else if (fruitType == typeof(Orange))
{
var oranges = connection.Query<Orange>("Select * from Oranges");
return oranges;
}
}
}
public class Fruit { }
public class Orange : Fruit { }
public class Banana : Fruit { }
Upvotes: 1