5

NinjectをASP.NETMVC4と一緒に使用しています。リポジトリを使用しており、コンストラクターインジェクションを実行して、リポジトリをコントローラーの1つに渡します。

これは私のリポジトリインターフェースです:

public interface IRepository<T> where T : TableServiceEntity
{
    void Add(T item);
    void Delete(T item);
    void Update(T item);
    IEnumerable<T> Find(params Specification<T>[] specifications);
    IEnumerable<T> RetrieveAll();
    void SaveChanges();
}

以下はのAzureTableStorageRepository実装ですIRepository<T>

public class AzureTableRepository<T> : IRepository<T> where T : TableServiceEntity
{
    private readonly string _tableName;
    private readonly TableServiceContext _dataContext;

    private CloudStorageAccount _storageAccount;
    private CloudTableClient _tableClient;

    public AzureTableRepository(string tableName)
    {
        // Create an instance of a Windows Azure Storage account
        _storageAccount = CloudStorageAccount.Parse(ConfigurationManager.ConnectionStrings["StorageConnectionString"].ConnectionString);

        _tableClient = _storageAccount.CreateCloudTableClient();
        _tableClient.CreateTableIfNotExist(tableName);
        _dataContext = _tableClient.GetDataServiceContext();
        _tableName = tableName;
    }

汎用テーブルリポジトリを使用してデータをAzureに永続化していたため、必要なtableNameパラメーターに注意してください。

そして最後に私は次のコントローラーを持っています。

public class CategoriesController : ApiController
{
    static IRepository<Category> _repository;

    public CategoriesController(IRepository<Category> repository)
    {
        if (repository == null)
        {
            throw new ArgumentNullException("repository");
        }

        _repository = repository;
    }

次に、リポジトリをコントローラに挿入します。そこで、バインディングを含むモジュールを作成しました。

/// <summary>
/// Ninject module to handle dependency injection of repositories
/// </summary>
public class RepositoryNinjectModule : NinjectModule
{
    public override void Load()
    {
        Bind<IRepository<Category>>().To<AzureTableRepository<Category>>();
    }
}

モジュールのロードは、NinjectWebCommon.cs

/// <summary>
    /// Creates the kernel that will manage your application.
    /// </summary>
    /// <returns>The created kernel.</returns>
    private static IKernel CreateKernel()
    {
        var kernel = new StandardKernel();
        kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
        kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

        RegisterServices(kernel);
        return kernel;
    }

    /// <summary>
    /// Load your modules or register your services here!
    /// </summary>
    /// <param name="kernel">The kernel.</param>
    private static void RegisterServices(IKernel kernel)
    {
        // Load the module that contains the binding
        kernel.Load(new RepositoryNinjectModule());

        // Set resolver needed to use Ninject with MVC4 Web API
        GlobalConfiguration.Configuration.DependencyResolver = new NinjectResolver(kernel);
    } 

これDependencyResolverは、NinjectのDependencyResolver実装であり、これをWebApiアプリケーションSystem.Web.Mvc.IDependencyResolverに割り当てることができないために作成されました。GlobalConfiguration.Configuration

したがって、これらすべてが整った状態で、Ninjectパーツは実際にはコントローラーに正しい型を注入していますが、NinjectはのコンストラクターにtableNameパラメーターを注入できませんAzureTableRepository

この場合、どうすればこれを行うことができますか?多くの記事とninjectのドキュメントを参照して、パラメーターの使用方法を確認しましたが、機能させることができないようです。

どんな助けでもいただければ幸いです。

4

2 に答える 2

10

私は次のWithConstructorArgument()ような方法を使用します...

Bind<IRepository<Category>>().To<AzureTableRepository<Category>>()
    .WithConstructorArgument("tableName", "categories");

リポジトリ設計の残りの部分は、おそらく別の質問です。IMHOテーブルを作成したり、ctorで重い物を持ち上げたりするのは大したことではないようです。

于 2012-12-17T20:59:38.220 に答える
0

その間、私はプロバイダーと遊んでそのトリックを試してみましたが、うまくいくようです。

これが良いアイデアなのか、それともやり過ぎなのかはわかりませんが、これが私が行ったことです。汎用プロバイダークラスを作成しました。

public abstract class NinjectProvider<T> : IProvider
{
    public virtual Type Type { get; set; }
    protected abstract T CreateInstance(IContext context);

    public object Create(IContext context)
    {
        throw new NotImplementedException();
    }

    object IProvider.Create(IContext context)
    {
        throw new NotImplementedException();
    }

    Type IProvider.Type
    {
        get { throw new NotImplementedException(); }
    }
}

そして、それをAzureTableRepositoryProviderに実装しました。(Tは、複数のエンティティタイプに対して同じリポジトリを持つことをサポートします。)

public class AzureTableRepositoryProvider<T> : Provider<AzureTableRepository<T>> where T : TableServiceEntity
{
    protected override AzureTableRepository<T> CreateInstance(IContext context)
    {
        string tableName = "";

        if (typeof(T).Name == typeof(Category).Name)
        {
            // TODO Get the table names from a resource
            tableName = "categories";
        }
        // Here other types will be addedd as needed

        AzureTableRepository<T> azureTableRepository = new AzureTableRepository<T>(tableName);

        return azureTableRepository;
    }
}

このプロバイダーを使用することで、リポジトリを操作するための適切なテーブル名を渡すことができます。しかし、私にとっては、2つの質問が残っています。

  1. これは良い習慣ですか、それとももっと簡単にできるでしょうか?
  2. NinjectProviderクラスには、2つのnotImplementedExceptionケースがあります。どうすればこれらを解決できますか?次のリンクのサンプルコードを使用しましたが、プロバイダーが抽象的であり、コードにcreateメソッドの本文がないため、機能しません...ここにリンクの説明を入力してください
于 2012-12-16T01:41:20.787 に答える