Skip to main content
added 697 characters in body
Source Link

Consume the derivatives like this:

public class EntityConsumer
{
    private User.IBusiness       userBusiness;
    private Permission.IBusiness permissionBusiness;

    public EntityConsumer(User.IBusiness userBusiness, Permission.IBusiness permissionBusiness) { /* assign dependencies */ }

    public void ConsumeEntities()
    {
        var users       = new User.DataObjectList();
        var permissions = this.permissionBusiness.LoadAll();

        users.Add
        (new User.DataObject()
        {
            // Assign property values
        });

        this.userBusiness.Save(users);

    }
}

The benefit to writing the types this way is added type safety and less casting of types in the abstract classes. Its the equivalent of ArrayListArrayList vs ListList<T> on a larger scale.

The benefit to writing the types this way is added type safety and less casting of types in the abstract classes. Its the equivalent of ArrayList vs List on a larger scale.

Consume the derivatives like this:

public class EntityConsumer
{
    private User.IBusiness       userBusiness;
    private Permission.IBusiness permissionBusiness;

    public EntityConsumer(User.IBusiness userBusiness, Permission.IBusiness permissionBusiness) { /* assign dependencies */ }

    public void ConsumeEntities()
    {
        var users       = new User.DataObjectList();
        var permissions = this.permissionBusiness.LoadAll();

        users.Add
        (new User.DataObject()
        {
            // Assign property values
        });

        this.userBusiness.Save(users);

    }
}

The benefit to writing the types this way is added type safety and less casting of types in the abstract classes. Its the equivalent of ArrayList vs List<T> on a larger scale.

Source Link

I know that this is an old question, but one very valid reason to use a class as a namespace (a non-static one at that) is that C# does not support the definition of parametric or generic namespaces. I've written up a blog post on this very topic here: http://tyreejackson.com/generics-net-part5-generic-namespaces/.

The gist of it is, when using generics to abstract huge swaths of boilerplate code, it is sometimes necessary to share multiple generic parameters between related classes and interfaces. The conventional way to do this would be to redefine the generic parameters, constraints and all in each interface and class signature. Over time this can lead to a proliferation of parameters and constraints not to mention constantly having to qualify the related types by forwarding the type parameters from one type to the type arguments of the related type.

Using an outer Generic class and nesting the related types within can dramatically DRY up the code and simplify its abstraction. One can then derive the parametric namespace class with a concrete implementation that supplies all of the concrete details.

Here is a trivial example:

public  class   Entity
                <
                    TEntity, 
                    TDataObject, 
                    TDataObjectList, 
                    TIBusiness, 
                    TIDataAccess, 
                    TIdKey
                >
        where   TEntity         : Entity<TEntity, TDataObject, TDataObjectList, TIBusiness, TIDataAccess, TIdKey>, subclassed
        where   TDataObject     : Entity<TEntity, TDataObject, TDataObjectList, TIBusiness, TIDataAccess, TIdKey>.BaseDataObject, subclassed
        where   TDataObjectList : Entity<TEntity, TDataObject, TDataObjectList, TIBusiness, TIDataAccess, TIdKey>.BaseDataObjectList, subclassed
        where   TIBusiness      : Entity<TEntity, TDataObject, TDataObjectList, TIBusiness, TIDataAccess, TIdKey>.IBaseBusiness
        where   TIDataAccess    : Entity<TEntity, TDataObject, TDataObjectList, TIBusiness, TIDataAccess, TIdKey>.IBaseDataAccess
{

    public class    BaseDataObject
    {
        public TIdKey Id { get; set; }
    }

    public class BaseDataObjectList : Collection<TDataObject> {}

    public interface IBaseBusiness
    {

        TDataObject     LoadById(TIdKey id);
        TDataObjectList LoadAll();
        void            Save(TDataObject item);
        void            Save(TDataObjectList items);
        void            DeleteById(TIdKey id);
        bool            Validate(TDataObject item);
        bool            Validate(TDataObjectList items);

    }

    public interface IBaseDataAccess
    {

        TDataObject     LoadById(TIdKey id);
        TDataObjectList LoadAll();
        void            Save(TDataObject item);
        void            Save(TDataObjectList items);
        void            DeleteById(TIdKey id);

    }

}

Used like this:

public  class   User 
:
                Entity
                <
                    User, 
                    User.DataObject, 
                    User.DataObjectList, 
                    User.IBusiness, 
                    User.IDataAccess, 
                    Guid
                >
{
    public class DataObject : BaseDataObject
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }

    public class DataObjectList : BaseDataObjectList {}

    public interface IBusiness : IBaseBusiness
    {
        void DeactivateUserById(Guid id);
    }

    public interface IDataAcccess : IBaseDataAccess {}
}

The benefit to writing the types this way is added type safety and less casting of types in the abstract classes. Its the equivalent of ArrayList vs List on a larger scale.