Шаблон Ninject и репозитория с интерфейсами - PullRequest
1 голос
/ 29 июня 2010

Это структура интерфейсов / классов, которая у меня сейчас есть:

BaseContentObject абстрактный класс

public abstract class BaseContentObject : IEquatable<BaseContentObject>
{
...
}

Конкретный класс страницы

public class Page : BaseContentObject
{
...
}

Интерфейс репозитория

public interface IContentRepository<T>
    {
        // common methods for all content types
        void Insert(T o);
        void Update(T o);
        void Delete(string slug);
        void Delete(ContentType contentType, string slug);
        IEnumerable<T> GetInstances();
        T GetInstance(ContentType contentType, string slug);
        T GetInstance(string contentType, string slug);
        T GetInstance(string slug);
        IEnumerable<string> GetSlugsForContentType(int limit = 0, string query = "");
        ContentList GetContentItems();
        bool IsUniqueSlug(string slug);
        string ObjectPersistanceFolder { get; set; }
    }

Реализация общего интерфейса (для всех классов контента, которые наследуют класс BaseContentObject)

    public class XmlRepository<T> : IContentRepository<BaseContentObject>
    {
        public string ObjectPersistanceFolder { get; set; }

        public XmlRepository()
        {
            ObjectPersistanceFolder = Path.Combine(XmlProvider.DataStorePhysicalPath, typeof(T).Name);
            if (!Directory.Exists(ObjectPersistanceFolder))
                Directory.CreateDirectory(ObjectPersistanceFolder);
        }
...
}

Репозиторий для конкретного контента

public class XmlPagesRepository : XmlRepository<Page> { }

Правило Ninject в global.asax.cs

Bind<IContentRepository<Page>>().To<XmlPagesRepository>();

, что приводит к следующей ошибке времени компиляции:

*The type 'Namespace.XmlPagesRepository' cannot be used as type parameter 'TImplementation' in the generic type or method 'Ninject.Syntax.IBindingToSyntax<T>.To<TImplementation>()'. There is no implicit reference conversion from 'Namespace.XmlPagesRepository' to 'Namespace.IContentRepository<Namespace.Page>'.*

Я потратил довольно много времени на выяснение структуры классов и интерфейсов для поддержки потребностей своего бизнеса.Теперь я не знаю, как обойти эту ошибку Ninject.

Я хочу использовать эту структуру в контроллерах ASP.NET MVC, например:

    public IContentRepository<Page> ContentRepository { get; private set; }

    public PageController(IContentRepository<Page> repository)
    {
        ContentRepository = repository;
    }

1 Ответ

2 голосов
/ 30 июня 2010

Я думаю, что если вы создадите тестовый пример с использованием конкретных классов, вы обнаружите, что действительно не можете неявно преобразовать из XmlPagesRepository в IContentRepository<Page>. Это трудно понять, но если это преобразование возможно, я думаю, связать его, используя ToMethod:

Bind<IContentRepository<Page>>().ToMethod(x => (IContentRepository<Page>)kernel.Get<XmlPagesRepository>());

Изменить: Если посмотреть на это еще, преобразование невозможно. XmlRepository<Page> реализует IContentRepository<BaseContentObject>, а не IContentRepository<Page>. Неважно, что Page является BaseContentObject, приведение невозможно. Это не сработает, как вы хотели.

Edit2: «Реализация» относится к реализации интерфейса; Вы реализуете интерфейс и наследуете (или расширяете) класс. Без полного понимания того, что вы пытаетесь сделать, я бы спроектировал репозитории так:

public interface IPageRepository : IContentRepository<Page>
{
}

public interface XmlPageRepository : IPageRepository
{
    // implementation
}

Теперь вы можете иметь несколько реализаций IPageRepository и связать соответствующую реализацию, используя Ninject:

Bind<IPageRepository>().To<XmlPageRepository>();
...