Eu sei que essa é uma pergunta antiga, mas um motivo muito válido para usar uma classe como um espaço para nome (um não estático) é que o C # não suporta a definição de espaços para nome paramétricos ou genéricos. Eu escrevi uma postagem de blog sobre esse mesmo tópico aqui: http://tyreejackson.com/generics-net-part5-generic-namespaces/ .
A essência disso é que, ao usar genéricos para abstrair grandes faixas de código padrão, às vezes é necessário compartilhar vários parâmetros genéricos entre classes e interfaces relacionadas. A maneira convencional de fazer isso seria redefinir os parâmetros genéricos, restrições e tudo em cada interface e assinatura de classe. Com o tempo, isso pode levar a uma proliferação de parâmetros e restrições, sem mencionar constantemente a necessidade de qualificar os tipos relacionados, encaminhando os parâmetros de tipo de um tipo para os argumentos de tipo do tipo relacionado.
Usar uma classe Genérica externa e aninhar os tipos relacionados pode secar drasticamente o código e simplificar sua abstração. Pode-se derivar a classe de espaço para nome paramétrico com uma implementação concreta que fornece todos os detalhes concretos.
Aqui está um exemplo trivial:
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);
}
}
Usado assim:
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 {}
}
Consuma os derivados como este:
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);
}
}
O benefício de escrever os tipos dessa maneira é aumentar a segurança de tipos e diminuir a conversão de tipos nas classes abstratas. É o equivalente de ArrayList
vs List<T>
em uma escala maior.