Yukarıda listelenen diğer nedenlere ek olarak, yalnızca yuvalanmış sınıfları değil, aslında genel yuvalanmış sınıfları kullanmayı düşünmem için bir neden daha var. Aynı genel tür parametrelerini paylaşan birden çok genel sınıfla çalışanlar için, genel bir ad alanı bildirme yeteneği son derece yararlı olacaktır. Ne yazık ki, .Net (veya en azından C #) genel ad alanları fikrini desteklemiyor. Yani aynı amacı gerçekleştirmek için, aynı hedefi gerçekleştirmek için genel sınıfları kullanabiliriz. Mantıksal bir varlıkla ilgili aşağıdaki örnek sınıfları alın:
public class BaseDataObject
<
tDataObject,
tDataObjectList,
tBusiness,
tDataAccess
>
where tDataObject : BaseDataObject<tDataObject, tDataObjectList, tBusiness, tDataAccess>
where tDataObjectList : BaseDataObjectList<tDataObject, tDataObjectList, tBusiness, tDataAccess>, new()
where tBusiness : IBaseBusiness<tDataObject, tDataObjectList, tBusiness, tDataAccess>
where tDataAccess : IBaseDataAccess<tDataObject, tDataObjectList, tBusiness, tDataAccess>
{
}
public class BaseDataObjectList
<
tDataObject,
tDataObjectList,
tBusiness,
tDataAccess
>
:
CollectionBase<tDataObject>
where tDataObject : BaseDataObject<tDataObject, tDataObjectList, tBusiness, tDataAccess>
where tDataObjectList : BaseDataObjectList<tDataObject, tDataObjectList, tBusiness, tDataAccess>, new()
where tBusiness : IBaseBusiness<tDataObject, tDataObjectList, tBusiness, tDataAccess>
where tDataAccess : IBaseDataAccess<tDataObject, tDataObjectList, tBusiness, tDataAccess>
{
}
public interface IBaseBusiness
<
tDataObject,
tDataObjectList,
tBusiness,
tDataAccess
>
where tDataObject : BaseDataObject<tDataObject, tDataObjectList, tBusiness, tDataAccess>
where tDataObjectList : BaseDataObjectList<tDataObject, tDataObjectList, tBusiness, tDataAccess>, new()
where tBusiness : IBaseBusiness<tDataObject, tDataObjectList, tBusiness, tDataAccess>
where tDataAccess : IBaseDataAccess<tDataObject, tDataObjectList, tBusiness, tDataAccess>
{
}
public interface IBaseDataAccess
<
tDataObject,
tDataObjectList,
tBusiness,
tDataAccess
>
where tDataObject : BaseDataObject<tDataObject, tDataObjectList, tBusiness, tDataAccess>
where tDataObjectList : BaseDataObjectList<tDataObject, tDataObjectList, tBusiness, tDataAccess>, new()
where tBusiness : IBaseBusiness<tDataObject, tDataObjectList, tBusiness, tDataAccess>
where tDataAccess : IBaseDataAccess<tDataObject, tDataObjectList, tBusiness, tDataAccess>
{
}
Bu sınıfların imzalarını genel bir ad alanı kullanarak basitleştirebiliriz (yuvalanmış sınıflar aracılığıyla uygulanır):
public
partial class Entity
<
tDataObject,
tDataObjectList,
tBusiness,
tDataAccess
>
where tDataObject : Entity<tDataObject, tDataObjectList, tBusiness, tDataAccess>.BaseDataObject
where tDataObjectList : Entity<tDataObject, tDataObjectList, tBusiness, tDataAccess>.BaseDataObjectList, new()
where tBusiness : Entity<tDataObject, tDataObjectList, tBusiness, tDataAccess>.IBaseBusiness
where tDataAccess : Entity<tDataObject, tDataObjectList, tBusiness, tDataAccess>.IBaseDataAccess
{
public class BaseDataObject {}
public class BaseDataObjectList : CollectionBase<tDataObject> {}
public interface IBaseBusiness {}
public interface IBaseDataAccess {}
}
Ardından, Erik van Brakel'in daha önceki bir yorumda önerdiği gibi kısmi sınıfların kullanımı yoluyla, sınıfları ayrı iç içe dosyalara ayırabilirsiniz. Kısmi sınıf dosyalarını iç içe yerleştirmeyi desteklemek için NestIn gibi bir Visual Studio uzantısı kullanmanızı öneririm. Bu, "ad alanı" sınıf dosyalarının, iç içe geçmiş sınıf dosyalarını klasör benzeri bir şekilde organize etmek için de kullanılmasına izin verir.
Örneğin:
Entity.cs
public
partial class Entity
<
tDataObject,
tDataObjectList,
tBusiness,
tDataAccess
>
where tDataObject : Entity<tDataObject, tDataObjectList, tBusiness, tDataAccess>.BaseDataObject
where tDataObjectList : Entity<tDataObject, tDataObjectList, tBusiness, tDataAccess>.BaseDataObjectList, new()
where tBusiness : Entity<tDataObject, tDataObjectList, tBusiness, tDataAccess>.IBaseBusiness
where tDataAccess : Entity<tDataObject, tDataObjectList, tBusiness, tDataAccess>.IBaseDataAccess
{
}
Entity.BaseDataObject.cs
partial class Entity<tDataObject, tDataObjectList, tBusiness, tDataAccess>
{
public class BaseDataObject
{
public DataTimeOffset CreatedDateTime { get; set; }
public Guid CreatedById { get; set; }
public Guid Id { get; set; }
public DataTimeOffset LastUpdateDateTime { get; set; }
public Guid LastUpdatedById { get; set; }
public
static
implicit operator tDataObjectList(DataObject dataObject)
{
var returnList = new tDataObjectList();
returnList.Add((tDataObject) this);
return returnList;
}
}
}
Entity.BaseDataObjectList.cs
partial class Entity<tDataObject, tDataObjectList, tBusiness, tDataAccess>
{
public class BaseDataObjectList : CollectionBase<tDataObject>
{
public tDataObjectList ShallowClone()
{
var returnList = new tDataObjectList();
returnList.AddRange(this);
return returnList;
}
}
}
Entity.IBaseBusiness.cs
partial class Entity<tDataObject, tDataObjectList, tBusiness, tDataAccess>
{
public interface IBaseBusiness
{
tDataObjectList Load();
void Delete();
void Save(tDataObjectList data);
}
}
Entity.IBaseDataAccess.cs
partial class Entity<tDataObject, tDataObjectList, tBusiness, tDataAccess>
{
public interface IBaseDataAccess
{
tDataObjectList Load();
void Delete();
void Save(tDataObjectList data);
}
}
Görsel stüdyo çözüm gezginindeki dosyalar şu şekilde düzenlenir:
Entity.cs
+ Entity.BaseDataObject.cs
+ Entity.BaseDataObjectList.cs
+ Entity.IBaseBusiness.cs
+ Entity.IBaseDataAccess.cs
Ve genel ad alanını aşağıdaki gibi uygularsınız:
User.cs
public
partial class User
:
Entity
<
User.DataObject,
User.DataObjectList,
User.IBusiness,
User.IDataAccess
>
{
}
User.DataObject.cs
partial class User
{
public class DataObject : BaseDataObject
{
public string UserName { get; set; }
public byte[] PasswordHash { get; set; }
public bool AccountIsEnabled { get; set; }
}
}
User.DataObjectList.cs
partial class User
{
public class DataObjectList : BaseDataObjectList {}
}
User.IBusiness.cs
partial class User
{
public interface IBusiness : IBaseBusiness {}
}
User.IDataAccess.cs
partial class User
{
public interface IDataAccess : IBaseDataAccess {}
}
Ve dosyalar çözüm gezgininde şu şekilde organize edilecektir:
User.cs
+ User.DataObject.cs
+ User.DataObjectList.cs
+ User.IBusiness.cs
+ User.IDataAccess.cs
Yukarıdaki, bir dış sınıfı genel bir ad alanı olarak kullanmanın basit bir örneğidir. Geçmişte 9 veya daha fazla tür parametresi içeren "genel ad alanları" oluşturdum. Bu tür parametrelerini, özellikle yeni bir parametre eklerken, tür parametrelerini bilmek için gereken dokuz tür arasında senkronize tutmak zorunda kalmak sıkıcıydı. Genel ad alanlarının kullanılması, bu kodu çok daha yönetilebilir ve okunabilir hale getirir.