8

I have a code base I want to use for both an ASP.NET MVC and a WPF/MVVM front end. The business objects are implement as interfaces and the business logic uses these interfaces for passing data.

Say I have a property on my interface that implements IEnumerable. Is it possible to have different versions of this interface use different implementations of IEnumerable? An example of what I am trying to accomplish:

class Reporting
{
    public bool RunReport(IReportParams Params);
}

interface IReportParams
{
    IEnumerable<Guid> SelectedItems { get; }
    IEnumerable<StatusEnum> SelectedStatuses { get; }
}

class MvcReportParams : IReportParams
{
    public List<Guid> SelectedItems { get; set; }
    public List<StatusEnum> SelectedStatuses { get; set; }
}

class WpfReportParams : IReportParams
{
    public ObservableCollection<Guid> SelectedItems { get; set; }
    public ObservableCollection<StatusEnum> SelectedStatuses { get; set; }
}

Can this be done?

Edit: I should also have asked "how", because when I try this, I get errors similar to this:

'MvcReportParams' does not implement interface member 'IReportParams.SelectedStatuses'. 'MvcReportParams.SelectedStatuses' cannot implement 'IReportParams.SelectedStatuses' because it does not have the matching return type of 'System.Collections.Generic.IEnumerable'

ObservableCollection and List both absolutely implement IEnumerable, and so this does not seem to make sense to me.

Last Edit

Well, someone posted the answer, but they deleted it for some reason, so I can't mark it as the solution. Here's what I ended up doing:

interface IReportParams
{
    IEnumerable<Guid> SelectedItems { get; }
    IEnumerable<StatusEnum> SelectedStatuses { get; }
}

class MvcReportParams : IReportParams
{
    // Properties that the modelbinder dims and sets up
    public List<Guid> SelectedItems { get; set; }
    public List<StatusEnum> SelectedStatuses { get; set; }

    // Explicityly implement my interface
    IEnumerable<Guid> IReportParams.SelectedItems
    {
        get { return SelectedItems; }
    }

    IEnumerable<StatusEnum> IReportParams.SelectedStatuses
    {
        get { return SelectedStatuses; }
    }
}

class WpfReportParams : IReportParams
{
    // Properties that my view dims and modifies
    public ObservableCollection<Guid> SelectedItems { get; set; }
    public ObservableCollection<StatusEnum> SelectedStatuses { get; set; }

    // Explicityly implement my interface
    IEnumerable<Guid> IReportParams.SelectedItems
    {
        get { return SelectedItems; }
    }

    IEnumerable<StatusEnum> IReportParams.SelectedStatuses
    {
        get { return SelectedStatuses; }
    }
}

It's more lines of boilerplate code to write, but I like being more explicit anyways.

Stevoman
  • 976
  • 9
  • 25
  • 1
    Also, it would have been quicker for you to just try it than to write a question about it. – Sam Axe Mar 23 '12 at 20:00
  • @Boo Just what I was going to say Boo. Perhaps this is more a question about understanding why it works (or not) rather than does it work as the compiler will tell you sooner than stack overflow no matter how quick it's answered :) – dreza Mar 23 '12 at 20:03
  • Updated the question body to be clearer. – Stevoman Mar 23 '12 at 20:10
  • @Baconcheese Maybe you get the error because in your interface, there's no setter for `SelectedItems` and `SelectedStatuses` – Kamyar Mar 23 '12 at 20:14
  • 1
    @Kamyar A setter not declared in the interface is totally fine. – Paul Phillips Mar 23 '12 at 20:27
  • So for my slightly misleading comment above. You will need to modift your inplementation as others have described below. – Sam Axe Mar 23 '12 at 21:06

2 Answers2

9

I would probably implement this with read-only properties. It better pratice for the client to add/remove/update items in an existing collection rather than replace the collection altogether.

interface IReportParams
{
    IEnumerable<Guid> SelectedItems { get; }
    IEnumerable<StatusEnum> SelectedStatuses { get; }
}

class MvcReportParams : IReportParams
{
    public MvcReportParams()
    {
        SelectedItems = new Collection<Guid>();
        SelectedStatuses = new Collection<StatusEnum>();
    }

    public IEnumerable<Guid> SelectedItems { get; private set; }
    public IEnumerable<StatusEnum> SelectedStatuses { get; private set; }
}

class WpfReportParams : IReportParams
{
    public WpfReportParams()
    {
        SelectedItems = new ObservableCollection<Guid>();
        SelectedStatuses = new ObservableCollection<StatusEnum>();
    }

    public IEnumerable<Guid> SelectedItems { get; private set; }
    public IEnumerable<StatusEnum> SelectedStatuses { get; private set; }
}
Phil
  • 42,255
  • 9
  • 100
  • 100
0

Came across the same problem. Figured the interfaces which are being implemented need to be public as well.

public interface IReportParams
{
    IEnumerable<Guid> SelectedItems { get; }
    IEnumerable<StatusEnum> SelectedStatuses { get; }
}

This should resolve the problem.

Thanks, Subhajit