Generics as a property #7623
Replies: 3 comments 8 replies
-
Wouldn't the properties be of type |
Beta Was this translation helpful? Give feedback.
-
@HaloFour I believe the point here is to register some statically typed mappers to a const dictionary which has string keys. When you access dictionary by const key you get this typed model. I think this is something that is possible to do in TypeScript because generics are stripped down and you only have type "hints". What I don't get though is why dictionary and not just a class with lots of properties? Also, why not just use normal generics? On your example you have types initialized beforehand. You still have to manually initialize them in the end (as in example with .Add calls) |
Beta Was this translation helpful? Give feedback.
-
I've written code very much like this in the past - though it was using NHibernate, not Entity Framework - and I managed to do so without using reflection. FWIW, here's a recreation of the approach that I took ... Define an interface representing a mapping: public interface IModelMapping
{
string ApiEndpointKey { get; }
Model Convert(Table t);
}
and an abstract class implementing that interface: public abstract class CustomModel<T, M> : IModelMapping
where T : Table
where M : Model
{
public abstract string ApiEndpointKey { get; }
Model IModelMapping.Convert(Table t)
{
return Convert((T)t);
}
public abstract M Convert(T row);
} The explicit interface implementation converts types, and in "real world" code would do some checking to throw a useful exception if misused. Then define a public class PersonMapping : CustomModel<PersonTbl, Person>
{
public override Person Convert(PersonTbl row)
{
// ...
}
}
public class PetMapping : CustomModel<PetTbl, Pet>
{
public override Pet Convert(PetTbl row)
{
// ...
}
} Initialization of your dictionary is easy: Dictionary<string, IModelMapping> dict = new();
void Add(IModelMapping mapping) => dict.Add(mapping.ApiEndpointKey, mapping);
Add(new PersonMapping());
Add(new PetMapping()); And consumption pretty much fits your original brief: public ValueType<object> GetData(string endpoint)
{
// Check permissions
// Check authorization
// Handle OData skip, top, nextlink, etc.
var mapping = dict[endpoint];
var qry = context.Set<mapping.EFClass>.Where(filter).Select(r => mapping.Convert(r));
return qry.ToList();
} Based on the thread to date, it doesn't seem (to me) that you actually need a language feature to solve your specific problem. One last point - some interesting pivots can be achieved by putting an instance into a dynamic variable and then calling the method you know exists. You could then just write your conversion methods as: public class PersonMapping : CustomModel<PersonTbl, Person>
{
public Person Convert(PersonTbl row)
{
// ...
}
} And then call it as follows: public ValueType<object> GetData(string endpoint)
{
// Check permissions
// Check authorization
// Handle OData skip, top, nextlink, etc.
dynamic mapping = dict[endpoint];
var qry = context.Set<mapping.EFClass>.Where(filter).Select(r => mapping.Convert(r));
return qry.ToList();
} In this case, runtime dynamic dispatch calls the method you want, easy as. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
I would like to be able to set the generic class as a property on a class.
Ex:
In this class, I would be able to set the key to my relationship, the database model, and the business model. This would allow me to have a collection of these that I could use to handle conversion from the database to the model.
I could then create all of the relationships for each of my endpoints like this:
I would then be able to do something like this:
Having this ability would allow me to abstract out a bunch of busy work setting up the wiring. In my real world example, I have 120+ endpoints that are fairly similar outside of the EF class and the business model. But, because I can't do this, I have to create another custom class that has the conversion method as a delegate so that I can set the generics.
I hope this make sense, if not please reach out to me and I can show you (if inside MSFT) what I am working with.
Beta Was this translation helpful? Give feedback.
All reactions