Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to return generic class based on enum input?

Tags:

c#

enums

generics

I am writing a small email templating engine using Razor syntax to fill in the tokens. I have a few email types:

public enum EmailType { Welcome, Reminder }

These types have corresponding templates and models, so for example Welcome email has a template:

<p>Welcome, @Model.Name</p>

and a corresponding model:

public class WelcomeModel { public string Name { get; set; } }

Now I wanted to create a method that will force a correct model for given enum, I would imagine something like this:

public ITemplate<T> GenerateTemplate(EmailType emailType)
{
    switch (emailType)
    {
        case EmailType.Welcome:
            return new EmailTemplate<WelcomeModel>();

        case EmailType.Reminder:
            return new EmailTemplate<ReminderModel>();
    // ...
}

where EmailTemplate<T> : ITemplate<T>, so then I could chain the method:

engine
    .GenerateTemplate(EmailType.Welcome)
    .WithModel(new WelcomeModel()) // this knows it wants WelcomeModel
                                   // and should complain with compiler error otherwise

The code that I've shown here does not compile because T is unknown. However this T cannot be infered:

public ITemplate<T> GenerateTemplate<T>(EmailType emailType)

which leaves me with:

engine
    .GenerateTemplate<WelcomeModel>(EmailType.Welcome)
    .WithModel(new WelcomeModel());

That works, but I feel like I'm passing redundant information - both enum and model, while you can deduce one from another. I am not sure if I'm missing something from C# or maybe my whole concept is not good. I think I'm in a dead end since I think I cannot return two separate, strongly typed classes from one method.

Is it possible to return generic model based on enum input?

like image 274
trollsteen Avatar asked Oct 16 '22 00:10

trollsteen


1 Answers

Is it possible to return generic class based on enum input?

No. Not in a way that would be useful to the caller.

Your method returns ITemplate<T>. But T has to be defined as something at compile time. You cannot defer the definition to runtime, except by using late-binding (i.e. dynamic) or non-type-safe mechanisms (which negates the whole point of using generics).

Possibly if you could reframe your question and explain why it is you think it's reasonable to call a method that returns an open generic type ITemplate<T> without the call site understanding what the type parameter T actually is, a helpful solution could be found.

But as stated in your question thus far, the only real answer is, no that can't work and wouldn't make any sense if it could.

like image 138
Peter Duniho Avatar answered Oct 19 '22 00:10

Peter Duniho