views:

41

answers:

1

I have a base DLL which defines some basic structure and operation for a key concept within our business. This dll is then included in specific web services for each vendor that implement the specific business rules for interacting with that vendor. (While the basic concepts are the same the implementations are very different and can change independently.)

In the base dll I have a series of interfaces set up as such

public interface IVendor
{
    string Name { get; set; }    
}

public interface IVendor<TC> : IVendor where TC : IAccount
{
    IEnumerable<TC> Accounts { get; set; }
}

public interface IAccount
{
    string Name { get; set; }
}

public interface IAccount<TP, TC> : IAccount where TP : IVendor
                                             where TC : IExecutionPeriod
{
    TP Vendor{ get; set; }
    IEnumerable<TC> ExecutionPeriods { get; set; }
}

This continues down several more tiers, and everything compiles fine.

The problem comes when I try to implement this down in the service.

public class FirstVendor : IVendor<FirstVendorAccount>
{
    public string Name { get; set; }
    public IEnumerable<FirstVendorAccount> Accounts { get; set;}
}

public class FirstVendorAccount : IAccount<FirstVendor, FirstVendorExecutionPeriod>
{
    public FirstVendor Vendor { get; set; }
    public string Name { get; set; }
    public IEnumerable<FirstVendorExecutionPeriod> ExecutionPeriods { get; set; }
}

I get a compiler error that IVendor, IAccount, etc. do not have type parameters. Which is particularly odd because when I asked it to implement the interface it included all of the members from both relevant interfaces.

+1  A: 

It looks like you have a circular reference - FirstVendorAccount needs to know about FirstVendor before it can compile and vice versa.

Make one of these the 'dominant' class with the generic type, then the other can just return the base interface.

For instance:

public interface IVendor
{
    string Name { get; set; }    
}

public interface IVendor<TC> : IVendor where TC : IAccount
{
    IEnumerable<TC> Accounts { get; set; }
}

public interface IAccount
{
    string Name { get; set; }
}

// no longer needs IVendor<TC> before it can be compiled
public interface IAccount<TC> : IAccount where TC : IExecutionPeriod
{
    IVendor Vendor{ get; set; }
    IEnumerable<TC> ExecutionPeriods { get; set; }
}

It's worth looking at whether you really need all the generic typing - you may be better off with the non-generic underlying interfaces as these will be much easier to code with.

Keith