So che questa è una vecchia domanda, ma un motivo molto valido per usare una classe come spazio dei nomi (non statico) è che C # non supporta la definizione di spazi dei nomi parametrici o generici. Ho scritto un post sul blog su questo argomento molto qui: http://tyreejackson.com/generics-net -part5-generic-namespace / .
L'essenza di ciò è che, quando si usano i generici per estendere enormi quantità di codice boilerplate, a volte è necessario condividere più parametri generici tra classi e interfacce correlate. Il modo convenzionale per farlo sarebbe ridefinire i parametri generici, i vincoli e tutto in ogni interfaccia e firma di classe. Nel tempo questo può portare a una proliferazione di parametri e vincoli, senza menzionare costantemente la necessità di qualificare i tipi correlati inoltrando i parametri del tipo da un tipo agli argomenti tipo del tipo correlato.
Utilizzare una classe generica esterna e annidare i tipi correlati all'interno può drasticamente aumentare il codice e semplificarne l'astrazione. Si può quindi derivare la classe dello spazio dei nomi parametrico con un'implementazione concreta che fornisce tutti i dettagli concreti.
Ecco un esempio banale:
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);
}
}
Usato in questo modo:
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 le derivate in questo modo:
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);
}
}
Il vantaggio di scrivere i tipi in questo modo è stato aggiunto sicurezza del tipo e meno cast di tipi nelle classi astratte. È l'equivalente di ArrayList
rispetto a List<T>
su una scala più grande.