0

次のクラス/インターフェースを持つサービス層があります (IServices は空のインターフェースです):

 public interface IForoChanService<T> : IService
{
    T GetById(int id);

    IQueryable SearchBy(Expression<Func<T, bool>> predicate);

    IEnumerable<T> GetAll();

    int Create(T entity);

    void CreateMany(IEnumerable<T> entities);

    void Delete(T entity);

    void Delete(int id);

    void DeleteMany(IEnumerable<T> entities);

    void Update(T entity);

}

次に、その署名を一般的に実装する抽象クラスがあります。

    public abstract class ForoChanServiceBase<T> : IForoChanService<T> where T : EntityBase
{
    public T GetById(int id)
     {
         return ChanDbContext.Set<T>().Find(id);
     }
     //all the other methods as well
} 

そして最後に具象クラス:

    public class CategoryService : ForoChanServiceBase<Category>
{

}

AutoFac を使用して、これらのサービス (多くの場合: カテゴリ、クライアントなど) をコンストラクターに挿入しようとしています: 基本コントローラーがあります:

 public abstract class ForoChanBaseController: Controller
{

    protected ForoChanServiceBase<Post> PostService { get; private set; }
    protected ForoChanServiceBase<Comment> CommentService { get; private set; }
    protected ForoChanServiceBase<Category> CategoryService { get; private set; }

    protected ForoChanBaseController()
    {

    }

    protected ForoChanBaseController(
        ForoChanServiceBase<Post> postService,
        ForoChanServiceBase<Comment> commentService,
        ForoChanServiceBase<Category> categoryService)
    {
        PostService = postService;
        CommentService = commentService;
        CategoryService = categoryService;
    }

}

そして、次のようにautofacを設定しています:

        public static void ConfigureIoc()
    {
        var builder = new ContainerBuilder();

        builder.RegisterType<CommentService>().As<ForoChanServiceBase<Comment>>().InstancePerRequest();
        builder.RegisterType<CategoryService>().As<ForoChanServiceBase<Category>>().InstancePerRequest();
        builder.RegisterType<PostService>().As<ForoChanServiceBase<Post>>().InstancePerRequest();

        builder.Build();
    }

問題は、コントローラーで、guy (CategoryService)が nullであるサービスメソッドを使用する必要がある場合です。

        public ActionResult Create()
    {
        var p = new PostFormNewVm
        {
            Categories = CategoryService.GetAll().Select(c => new CategoryVm { Id = c.Id, Title = c.Title })
        };

        return View(p);
    }

このエラーに加えて、私は何か間違ったことをしていますか? 私はそれを機能させることはできません。

インターフェースも試してみました。

4

1 に答える 1

2

あなたにはアンチパターンForoChanBaseControllerである複数のコンストラクタが含まれています。この既定のコンストラクターが存在するため、オーバーロードされたコンストラクターの代わりにこのコンストラクターを使用する派生クラスがあり、依存関係が.null

このデフォルトの ctor がここに質問を投稿する原因ですが、設計にはさらに明らかでない問題があります。

  • デフォルトのコンストラクターを削除することはできますが、この基本クラスをまったく持たないようにしてください。基本クラスは、多くの場合、単一責任の原則に対する大きな違反であり、分野横断的な関心事やその他のユーティリティ関数を詰め込むために使用されます。この基本クラスの派生型を使用することにより、まったく使用しない可能性のある依存関係が強制的に要求されます。これにより、コードが複雑になり、テストが複雑になります。
  • インターフェイスがあるため、消費者は基本クラスIForoChanService<T>に依存するべきではありません。ForoChanServiceBase実際のところ、以前と同じアドバイスが当てはまります。この基本クラスはおそらくまったく存在しないはずです。
  • IForoChanService<T>消費者が一度に 1 つまたは 2 つのメソッドのみを使用するメソッドの大きな汎用ツール ボックスです。これは、 Interface Segregation Principleに違反していることを意味します。
  • IForoChanService<T>エンティティの削除を許可しない実装があるため、実装はLiskov Substitution Principleに違反する可能性があります。これにより、そのエンティティに存在しないDelete代わりに、呼び出しが例外で失敗します。Delete
于 2016-12-14T22:11:36.180 に答える