独自のライブラリであるデータ アクセス レイヤーには、ドメイン オブジェクトのデータベース テーブルを表す POCO クラスがあります。例として 1 つを使用できますが、それを と呼びましょうMyClassDTO
。これと同じようなオブジェクトが数十あります。
独自のライブラリにもある(そしてDALライブラリを参照する)私のビジネスロジックレイヤーには、各オブジェクトの実際のドメインオブジェクトクラスがあります。を使いましょうMyClass
。
BLL は API としてMyClassBll
、ドメイン ロジックとデータにアクセスするためにプレゼンテーション プロジェクト内でインスタンス化できる のような一連のクラスを公開します。
私の人生を楽にするために、ほとんどの BLL オブジェクトMyClassBll
はジェネリック抽象Bll<TModel,TDto>
クラスから継承します。したがって、たとえばMyClassBll
次のように宣言されます。
Public Class MyClassBll : Bll<MyClass,MyClassDto>
ここでのアイデアは、プレゼンテーション層が話す言語であるドメイン オブジェクトを取得する BLL のジョブが、それらを DAL が話す言語である DTO に変換し、その逆も同様であるということです。
さまざまなオブジェクトの作成が非常に簡単になりました。特に、必要に応じてジェネリック実装をオーバーライドし、単純な場合はそのままにしておくことができるためです。ここまでは順調ですね。
問題が発生したのは、プレゼンテーションで使用し始めたときだけです。参照として BLL ライブラリを含めましたがMyClassBLL,
、 の定義を認識していないため、 のメソッドを使用できませんMyClassDto
。これは、定義としてのメタデータにありMyClassBll
ます。
プレゼンテーション レイヤーが DAL クラスについて知る必要はありません。どうすればコンパイラを満足させることができますか? 現在の設計の柔軟性を維持しながら、プレゼンテーション層から DAL をさらに隠す方法はありますか?
参考までに、私の汎用 BLL クラスは次のようになります。
public abstract class Bll<TModel, TDto> : IBll<TModel, TDto>
where TModel : class
where TDto : class
{
protected User User;
protected static string[] AdminGroups;
protected bool IsAdmin;
protected static Func<UnitOfWork, GenericRepository<TDto>> Repository;
private void AdminCheck()
{
if (!IsAdmin)
{
throw new SecurityException("That Action Requires Admin Privileges");
}
}
public Bll(User user)
{
StaticMapBulder.initialize();
if (User == null)
{
throw new ArgumentNullException("User Can not be null");
}
user = User;
IsAdmin = false;
foreach (var AdminGroup in AdminGroups)
{
if (user.IsInGroup(AdminGroup))
{
IsAdmin = true;
}
}
}
public virtual TModel Insert(TModel ItemToAdd)
{
AdminCheck();
using (var uow = new UnitOfWork())
{
var OutgoingDto = MapModelToDto(ItemToAdd);
var InboundDto = Repository(uow).Insert(OutgoingDto);
uow.Save();
return MapDtoToModel(InboundDto);
}
}
public virtual List<TModel> GetAll()
{
using (var uow = new UnitOfWork())
{
var InboundDto = Repository(uow).Get();
var ModelList = new List<TModel>();
foreach (var item in InboundDto)
{
ModelList.Add(MapDtoToModel(item));
}
return ModelList;
}
}
public virtual TModel GetByID(int ID)
{
using (var uow = new UnitOfWork())
{
var InboundDto = Repository(uow).GetByID(ID);
return MapDtoToModel(InboundDto);
}
}
public virtual void Update(TModel ItemToUpdate)
{
AdminCheck();
using (var uow = new UnitOfWork())
{
var OutboundDto = MapModelToDto(ItemToUpdate);
Repository(uow).Update(OutboundDto);
uow.Save();
}
}
public virtual void Delete(TModel ItemToDelete)
{
using (var uow = new UnitOfWork())
{
var OutboundDto = MapModelToDto(ItemToDelete);
Repository(uow).Delete(OutboundDto);
uow.Save();
}
}
public virtual void DeleteByID(int ID)
{
using (var uow = new UnitOfWork())
{
Repository(uow).Delete(ID);
uow.Save();
}
}
virtual public TModel MapDtoToModel(TDto Dto)
{
return Mapper.Map<TModel>(Dto);
}
virtual public TDto MapModelToDto(TModel Model)
{
return Mapper.Map<TDto>(Model);
}
}
}
そのクラスの一般的な実装は次のようになります。
public class MyClassBll : Bll<MyClass, MyClassDto>
{
public MyClassBll(User user)
: base(user)
{
}
new protected static Func<UnitOfWork, GenericRepository<MyClassDto>> Repository = x => x.MyClassRepository;
new protected static string[] AdminGroups = { "MyClassAdministrators" };
}