In part 1 We talked about the web.config and the basic classes to get started with a provider model.  Part 2 covered the interface for the data object and the Provider.  Now in part 3 we will address the IProviderCollection and the IProviderRepository.

Back in part one we added a provider collection to the generic provider repository by taking the provider collection as a generic parameter.  Now we are going to define the ProviderCollection interfaces.  They are going to be ICreateProviderCollection, IReadProviderCollection, IUpdateProviderCollection, IDeleteProviderCollection and ICrudProviderCollection.

First ICreateProviderCollection

public interface ICreateProviderCollection<ProviderType, DataObject>
        where ProviderType : ICreateProvider<ProviderType, DataObject>
        where DataObject : ICreateDataObject<ProviderType,DataObject>
    {
        ProviderType this[string name] {get;}
        ProviderType this[int index] { get; }
        void Add(ProviderBase provider);
    }

We define to methods of getting back a provider, one by name and the other by it's index in the collection.  We also define a way to add a provider to the collection.

Next IReadProviderCollection

    public interface IReadProviderCollection<ProviderType, DataObject, IdType>
        where ProviderType : IReadProvider<ProviderType,DataObject, IdType>
        where DataObject : IReadDataObject<DataObject, IdType>
    {
        ProviderType this[string name] { get; }
        ProviderType this[int index] { get; }
        void Add(ProviderBase provider);
    }

Except for the where clause, it is identical to the ICreateProviderCollection;  In fact so are IUpdateProviderCollection and  IDeleteProviderCollections

    public interface IUpdateProviderCollection<ProviderType, DataObject>
        where ProviderType : IUpdateProvider<ProviderType, DataObject>
        where DataObject : IUpdateDataObject<ProviderType, DataObject>
    {
        ProviderType this[string name] { get; }
        ProviderType this[int index] { get; }
        void Add(ProviderBase provider);
    }

    public interface IDeleteProviderCollection<ProviderType, DataObject>
        where ProviderType : IDeleteProvider<ProviderType, DataObject>
        where DataObject : IDeleteDataObject<ProviderType, DataObject>
    {
        ProviderType this[string name] { get; }
        ProviderType this[int index] { get; }
        void Add(ProviderBase provider);
    }

The ICrudProviderCollection on the other hand is empty...

    public interface ICrudProviderCollection<ProviderType, DataObject, IdType> : 
        ICreateProviderCollection<ProviderType, DataObject>,
        IReadProviderCollection<ProviderType, DataObject, IdType>,
        IUpdateProviderCollection<ProviderType, DataObject>,
        IDeleteProviderCollection<ProviderType, DataObject>
        where ProviderType : ICrudProvider<ProviderType, DataObject, IdType>
        where DataObject : ICrudDataObject<ProviderType, DataObject, IdType>
    {
    }

This is because the methods and properties are defined on the other interfaces already.

So, let's move on to the IProviderRepository.

First we have the ICrudProviderRepository

public interface ICrudProviderRepository<ProviderCollectionType,ProviderType, DataObject, IdType> :
        ICreateProviderRepository<ProviderCollectionType, ProviderType, DataObject>,
        IReadProviderRepository<ProviderCollectionType, ProviderType, DataObject, IdType>,
        IUpdateProviderRepository<ProviderCollectionType, ProviderType, DataObject>,
        IDeleteProviderRepository<ProviderCollectionType, ProviderType, DataObject>
        where ProviderCollectionType : ProviderCollection,
            ICrudProviderCollection<ProviderType, DataObject, IdType>, new()
        where ProviderType : ProviderBase, ICrudProvider<ProviderType, DataObject, IdType>
        where DataObject : ICrudDataObject<ProviderType, DataObject, IdType>
    {
    }

Again all of the methods and properties are defined on the other interfaces. 

ICreateProviderRepository

    public interface ICreateProviderRepository<ProviderCollectionType,ProviderType,DataObject>
        where ProviderCollectionType : ProviderCollection, ICreateProviderCollection<ProviderType, DataObject>, new()
        where ProviderType : ProviderBase, ICreateProvider<ProviderType, DataObject>
        where DataObject : ICreateDataObject<ProviderType,DataObject>
    {
        ProvidersRepositoryGeneric<ProviderCollectionType, ProviderType> LoadedProviders { get; }

        void Create(DataObject item, IPrincipal user);
        void Create(DataObject item, String providerName, IPrincipal user);
        void Create(DataObject item, Int32 providerIndex, IPrincipal user);
        void Create(DataObject item, ProviderType provider, IPrincipal user);

    }

The interface defines 4 overloads of the create method.  The first, in a concret class, would use the default provider.  The second accepts the name of the provider and uses it to find the correct provider to use.  The 3 overload  takes the index of the provider in the collection to try and find the provider.  And last but not least is the 4th overload which accepts the provider itself.  The IReadProviderRepository, IUpdateProviderRepository and IDeleteProviderRepositorys all have these 4 overloads with similar signatures.  In IReadProviderRepository the read methods return a DataObject instead of taking one as a parameter.  Back in part one we defined the ProvidersRepositoryGeneric and this is where we use it.

IReadProviderRepository

    public interface IReadProviderRepository<ProviderCollectionType, ProviderType,DataObject,IdType>
        where ProviderCollectionType : ProviderCollection,IReadProviderCollection<ProviderType, DataObject, IdType>,new()
        where ProviderType : ProviderBase,IReadProvider<ProviderType, DataObject, IdType>
        where DataObject: IReadDataObject<DataObject,IdType>
    {
        ProvidersRepositoryGeneric<ProviderCollectionType,ProviderType> LoadedProviders{get;}

        DataObject GetById(IdType id, IPrincipal user);
        DataObject GetById(IdType id, String providerName, IPrincipal user);
        DataObject GetById(IdType id, Int32 providerIndex, IPrincipal user);
        DataObject GetById(IdType id, ProviderType provider, IPrincipal user);
    }

IUpdateProviderRepository

    public interface IUpdateProviderRepository<ProviderCollectionType,ProviderType,DataObject>
        where ProviderCollectionType : ProviderCollection, IUpdateProviderCollection<ProviderType, DataObject>, new()
        where ProviderType : ProviderBase, IUpdateProvider<ProviderType, DataObject>
        where DataObject : IUpdateDataObject<ProviderType,DataObject>
    {
        ProvidersRepositoryGeneric<ProviderCollectionType, ProviderType> LoadedProviders { get; }

        void Update(DataObject item, IPrincipal user);
        void Update(DataObject item, String providerName, IPrincipal user);
        void Update(DataObject item, Int32 providerIndex, IPrincipal user);
        void Update(DataObject item, ProviderType provider, IPrincipal user);
    }

IDeleteProviderRepository

    public interface IDeleteProviderRepository<ProviderCollectionType, ProviderType,DataObject>
        where DataObject : IDeleteDataObject<ProviderType, DataObject>
        where ProviderCollectionType : ProviderCollection, IDeleteProviderCollection<ProviderType, DataObject>, new()
        where ProviderType : ProviderBase, IDeleteProvider<ProviderType, DataObject>
    {
        ProvidersRepositoryGeneric<ProviderCollectionType, ProviderType> LoadedProviders { get; }

        void Delete(DataObject item, IPrincipal user);
        void Delete(DataObject item, String providerName, IPrincipal user);
        void Delete(DataObject item, int providerIndex, IPrincipal user);
        void Delete(DataObject item, ProviderType provider, IPrincipal user);
    }

Our basic interfaces are done, now we need to create classes that use them and build a provider

Next : Generics, Interfaces, Providers and You - Part 4: Building the Classes