Ich weiß, dass dies eine alte Frage ist, aber ein sehr triftiger Grund, eine Klasse als Namespace zu verwenden (ein nicht statischer Grund), ist, dass C # die Definition von parametrischen oder generischen Namespaces nicht unterstützt. Ich habe zu genau diesem Thema hier einen Blogeintrag verfasst : http://tyreejackson.com/generics-net-part5-generic-namespaces/ .
Das Wesentliche dabei ist, dass bei der Verwendung von Generika zum Abstrahieren großer Mengen von Boilerplate-Code manchmal mehrere generische Parameter zwischen verwandten Klassen und Schnittstellen geteilt werden müssen. Der herkömmliche Weg, dies zu tun, besteht darin, die generischen Parameter, Einschränkungen und alles in jeder Schnittstelle und Klassensignatur neu zu definieren. Im Laufe der Zeit kann dies zu einer Zunahme von Parametern und Einschränkungen führen, ganz zu schweigen davon, dass die verwandten Typen ständig qualifiziert werden müssen, indem die Typparameter von einem Typ an die Typargumente des verwandten Typs weitergeleitet werden.
Durch die Verwendung einer äußeren generischen Klasse und das Verschachteln der zugehörigen Typen kann der Code drastisch getrocknet und seine Abstraktion vereinfacht werden. Man kann dann die parametrische Namespace-Klasse mit einer konkreten Implementierung ableiten, die alle konkreten Details liefert.
Hier ist ein triviales Beispiel:
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);
}
}
So verwendet:
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 {}
}
Verbrauchen Sie die Derivate wie folgt:
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);
}
}
Der Vorteil beim Schreiben der Typen auf diese Weise liegt in der erhöhten Typensicherheit und der geringeren Umwandlung von Typen in abstrakte Klassen. Es ist das Äquivalent von ArrayList
vs List<T>
in größerem Maßstab.