简体   繁体   中英

List of DTO with Dynamic type of propertie

I'm trying to create a Dto like this:

public class GroupEventualityDto
{
    public int Id { get; set; }
    public int IdGroup { get; set; }
    public int IdEventuality { get; set; }
    public ???? Value { get; set; }
}

Note that the propertie Value its a dynamic type (only decimal, string or int). My achieve its adding a List<GroupEventualityDto> where the GroupEventualityDto have a type of data decimal, int or another case type of that. How to achieve that?

The only way to do what you want is to use a base class then inherit this base class and make this derived class generic like so:

public abstract class GroupEventualityDto
{
    public int Id { get; set; }
    public int IdGroup { get; set; }
    public int IdEventuality { get; set; }
}

public class GroupEventualityDto<T> : GroupEventualityDto
{

    public T Value { get; set; }
}

public static void Main(string[] args)
{
    var one = new GroupEventualityDto<int>() {Value = 123};
    var two = new GroupEventualityDto<string>() {Value = "string"};
    var three = new GroupEventualityDto<double>() {Value = 45.54};

    var list = new List<GroupEventualityDto>()
    {
        one,
        two,
        three
    };

    foreach (var val in list)
    {
        Console.WriteLine(val.GetType());
    }
}

You will have to deal with casting them back though when you want to get it out of the list.

Why just not a generic type like this ?

public class GroupEventualityDto<T>
{
    public int Id { get; set; }
    public int IdGroup { get; set; }
    public int IdEventuality { get; set; }
    public T Value { get; set; }
}

If I understand your problem correctly you want to have a generic class but also want to restrict the type of the Value to specific types.

Working but rather ugly generic type restriction

public class GroupEventualityDto<T>
{
    public int Id { get; set; }
    public int IdGroup { get; set; }
    public int IdEventuality { get; set; }
    public T Value { get; set; }

    public GroupEventualityDto(){
        if(!(Value is int || Value is decimal || Value is string)) throw new ArgumentException("The GroupEventualityDto generic type must be either an int, decimal or string");
    }
}

In my second attempt I'll just check the type of Value to be one of the intended types and throw an ArgumentException if this is not the case.

Now, when I use

GroupEventualityDto<int> testTrue = new GroupEventualityDto<int>();

everything will just work the way I think the question is meant to implement this class.

If I'm trying to use a type which shouldn't work for that class as in

GroupEventualityDto<float> testFalse = new GroupEventualityDto<float>();


// System.ArgumentException: The GroupEventualityDto generic type must be either an int, decimal or string

the above exception will be thrown just like expected.

You can try out the working code here . I hope this approach might help you!

That being said, it could probably be done a tad more readable and enhance usability if the types were stored in an array of valid types but I couldn't wrap my head around that, unfortunately.


Type constraints - which won't work here

At first glance, I would have thought using type constraints like in

public class GroupEventualityDto<T> where T: int, decimal, string

would work. However, it turns out that this does not work.

'int' is not a valid constraint. A type used as a constraint must be an interface, a non-sealed class or a type parameter.

A closely related question has been asked here already and it turns out that type constraints can't be restricted with a constraint in that case.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM