Ninject:构造函数参数



我将Ninject与ASP.NET MVC 4一起使用。我正在使用存储库,并希望进行构造函数注入,以将存储库传递给其中一个控制器。

这是我的存储库界面:

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();
}

下面的AzureTableStorageRepositoryIRepository<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;
}

请注意需要tableName参数,因为我使用通用表存储库将数据持久化到Azure。

最后我有了下面的控制器。

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实现了System.Web.Mvc.IDependencyResolver,而这不能分配给WebApi应用程序的GlobalConfiguration.Configuration

因此,有了所有这些,Ninject部分实际上在Controller中注入了正确的类型,但Ninject无法在AzureTableRepository的构造函数中注入tableName参数。

在这种情况下,我该怎么做?我查阅了很多文章和ninject文档来了解如何使用参数,但我似乎无法使其正常工作。

如有任何帮助,我们将不胜感激。

我会使用WithConstructorArgument()方法,比如。。。

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

存储库设计的其余部分可能是另一个问题。IMHO创建一张桌子或在ctor中做任何繁重的工作似乎都是一个很大的禁忌。

与此同时,我一直在和提供商玩这个把戏,似乎奏效了。

我不知道这是个好主意还是太夸张了,但以下是我所做的:我创建了一个通用的提供者类:

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;
}
}

通过使用此提供程序,我可以为要使用的存储库传递正确的表名。但对我来说,还有两个问题:

  1. 这是一个好的做法,还是我们可以做得简单得多
  2. 在NinjectProvider类中,我有两种notImplementedException情况。我该如何解决这些问题?我使用了以下链接中的示例代码,但这不起作用,因为提供程序是抽象的,并且代码没有create方法的主体。。。在此处输入链接描述

相关内容

最新更新