2012-12-15 6 views
5

ASP.NET MVC 4와 함께 Ninject를 사용하고 있습니다. 저장소를 사용하고 있으며 저장소 중 하나에 저장소에 전달하기 위해 생성자 삽입을 수행하려고합니다.Ninject : 생성자 매개 변수

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

주 I가 데이터를 유지하기 위해 일반 테이블 저장소를 사용했기 때문에 TABLENAME 매개 변수가 필요합니다 :

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

모듈의 로딩이 이루어집니다를 Ninject에의 DependencyResolverSystem.Web.Mvc.IDependencyResolver를 구현하고이에 할당 할 수 없기 때문에 DependencyResolver 제작 한 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); 
    } 

WebApi 응용 프로그램의 GlobalConfiguration.Configuration.

Ninject 부분은 실제로 컨트롤러에 올바른 형식을 주입하지만 Ninject는 생성자 에 tableName 매개 변수를 삽입 할 수 없습니다.

이 경우 어떻게해야합니까? 나는 많은 기사와 ninject 문서를 참조하여 매개 변수를 어떻게 사용할 수 있는지 보았지만 작동시키지 못했습니다.

도움을 주시면 감사하겠습니다.

답변

10

내가 같은 WithConstructorArgument() 방법을 사용하는 것 ...

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

저장소 디자인의 나머지는 아마도 또 다른 문제이다. IMHO 테이블을 만들거나 ctor에서 무거운 것을하는 것은 큰 노약자처럼 보입니다.

+0

나는 생성자를 제거 할 것이라고 생각한다. 왜냐하면 실제로는 ctor에서 초기화를 많이하는 것이 좋지 않기 때문이다. Thx! –

0

그동안 나는 트릭을 시도하고 수행하는 데 Providers와 함께 놀았으며 효과가있는 것으로 보입니다.

이 좋은 생각하거나 여기 과잉이다하지만 만약 내가 한 일을하는 경우 나도 몰라 : 나는 일반적인 프로 바이더 클래스 만들었습니다

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

를 I가 작동하는 저장소에 적합한 테이블 이름으로 전달할 수있는 본 공급자를 사용하여. 하지만 나에게 두 가지 질문이 남습니다.

  1. 이 좋은 사례입니까, 아니면 훨씬 더 간단하게 할 수 있습니까?
  2. NinjectProvider 클래스에는 두 개의 notImplementedException 경우가 있습니다. 어떻게 해결할 수 있을까요? 다음 링크에서 샘플 코드를 사용했지만 Provider가 추상이고 코드에 create 메서드의 본문이 없으므로 작동하지 않습니다.enter link description here
관련 문제