Craig
Craig

Reputation: 18694

c# methods that takes an Interface?

I am new to Interfaces.

I have a lot of objects that I pass as DTOs through my layers to the UI. Some of them are quite complex (Quite a few properties), but I only want to use them, in certain circumstances, in DropDown lists. These DTOs all have an int Id, and a string Description.

I would like to create a static function that takes a List<> of one of these objects, and returns a List<SelectListItem>

So, I am trying to use Interfaces for the first time.

I created an Interface:

public interface IListableItem
{
    int Id { get; set; }
    string Description { get; set; }
}

And then, I assigned that interface to one of my DTO objects I am trying to convert:

public class CategoryDto : BaseDto , IListableItem
{
    public int PortfolioId { get; set; }
    public string Description { get; set; }
    public List<ExtendedSubCategoryDto> SubCategories { get; set; }
    public bool IsExpenseCategory { get; set; }

    public CategoryDto()
    {
        SubCategories = new List<ExtendedSubCategoryDto>();
    }
}

Then, I created my generic method that takes a list of the category dtos, and will hopefully return a list

public static List<SelectListItem> TranslateToSelectList(List<IListableItem> source)
{
    var reply = source.Select(item => new SelectListItem
    {
        Value = item.Id.ToString(CultureInfo.InvariantCulture), Text = item.Description
    }).ToList();

    return reply;
}

But, when I attempt to use this method, passing it a List, it fails.

    model.Categories =
        Translator.TranslateToSelectList(MyService.GetCategoriesByPortfolioId());

GetCategoriesByPortfolioId returns a List.

It's failing with the error:

CategoryDto is not assignable to IListableItem

It's probably a basic Interface understanding issue on my part, but what am I doing wrong, and how can I fix it?

Upvotes: 0

Views: 104

Answers (1)

Erti-Chris Eelmaa
Erti-Chris Eelmaa

Reputation: 26268

If your method expects List<IListableItem>, you can't pass List<CategoryDTO>.

If that would be possible, you could Add different instances of elements that implement the interface IListableItem into a collection that is holding CategoryDTO elements, and read them.

Ultimately, that wouldn't make sense.

You can fix it, if you use IEnumerable interface. That allows covariance(going from higher type to lower type in generic type parameter).

The reason it works, is that IEnumerable is a "read-only view" of collection, thus you can't really add anything to it - plus what's important, the type parameter is marked as covariant.

public static List<SelectListItem> TranslateToSelectList(
 IEnumerable<IListableItem> source)
{..}

Upvotes: 5

Related Questions