Reputation: 39
Being a beginning programmer to the Object Oriented Programming languages, I have recently taken up on C#. I am currently making a web application which is the following:
The web page consists of several drop-down menus that are supposed to be filled up with results from a MongoDB database. In this Database, I have got 8 collections which each an unknown amount of objects, each having 7 properties (and a collection name). I have used an interface for all of the similarities between the collections, as shown below:
namespace TestMVC.Models
{
public interface Product
{
string collectionName;
ObjectId Id { get; set; }
double Prijs { get; set; }
string Productlink { get; set; }
string Productnaam { get; set; }
}
}
and then I would like to perform a select query to show each and every record of the specific collection using the code shown below:
var collection = DatabaseConnect().GetCollection<Product>(collectionName);
var query =
from Product in collection.AsQueryable<Product>()
orderby Product.Prijs
select Product;
foreach (Product prd in query){
//... Do something
}
This is where my problem starts. I do not know beforehand what collection is retrieved during runtime, so I am trying to make a generic function with 2 parameters that would handle all 8 types of collections from the database.
public string databaseResult(string collectionName, Type className)
And I call it using:
databaseResult('motherboards', typeof(Motherboards));
So when I inject all this into the code stated above, I get an error in the following line
var collection = DatabaseConnect().GetCollection<className>(collectionName);
saying:
"The type or namespace name "className" could not be found (are you missing a using directive or an assembly reference?)"
Which obviously means the code is not treating the "className" in between the <> symbols as the class name stated in the parameter... So this is my problem.
I first tried using "class" instead of "Type" in the parameters, which obviously did not work because "class" is not a type (apparently). I searched a bit on stack overflow, and learned to use typeof to return the class name... which is only useful if you need to instantiate an object of the said class. Unfortunately MongoDB does not work properly with instances of classes: it needs to work with the classes themselves (as far as I know).
The above paragraph is just to show you that I HAVE done some research myself, but I am at a loss in understanding C# jargon like presented on msdn.com. I am looking for an answer that will make me understand WHAT to do in order to make this code work, and WHY, and an explanation on the latter (preferably without the msdn.com jargon I mentioned before).
I apologize for the long read but I do still hope somebody is willing to help. Many thanks in advance.
Upvotes: 1
Views: 130
Reputation: 51420
You have to use generics for this.
public string DatabaseResult<T>(string collectionName)
where T : IProduct
{
var collection = DatabaseConnect().GetCollection<T>(collectionName);
// ...
}
You call this like this:
DatabaseResult<Motherboard>("motherboards");
In this example T
is a placeholder for a type. It gets substituted by Motherboard
.
Note the where T : IProduct
clause. It sets a constraint on T
to only allow classes that implement IProduct
.
This works because you can use T
in places where a type name is expected (like typeof(T)
). On the other hand, when you use a Type className
parameter in your code, className
is just a variable like any other. The Type
class doesn't make it special in any way, so you can't write typeof(className)
or GetCollection<className>
for instance, because a type name is expected there, not a variable holding a reference to a Type
instance.
Also, as a convention in C#, interfaces should start with I
(ie IProduct
), and method names should be PascalCased.
Upvotes: 2