【问题标题】:Ninject and repository pattern with interfaces带有接口的 Ninject 和存储库模式
【发布时间】:2011-03-09 17:16:04
【问题描述】:

这是我现在拥有的接口/类结构:

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

global.asax.cs 中的 Ninject 规则

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

【问题讨论】:

  • 给出编译时错误不会有什么坏处 - 它会向遇到此问题并解决它的人开放,甚至不将其视为一个大问题。

标签: c# asp.net-mvc ninject ninject-2


【解决方案1】:

我认为,如果您使用具体类创建测试用例,您会发现确实无法从XmlPagesRepository 隐式转换为IContentRepository&lt;Page&gt;。很难理解,但如果可以进行这种转换,那么我认为使用ToMethod 绑定它:

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

编辑:再看一遍,转换是不可能的。 XmlRepository&lt;Page&gt; 实现IContentRepository&lt;BaseContentObject&gt; 不是IContentRepository&lt;Page&gt;。 Page 是 BaseContentObject 并不重要,演员是不可能的。这不会按您的预期工作。

Edit2:“Implement”是指实现一个接口;您实现一个接口并从(或扩展)一个类。在不完全了解您要做什么的情况下,这就是我设计存储库的方式:

public interface IPageRepository : IContentRepository<Page>
{
}

public interface XmlPageRepository : IPageRepository
{
    // implementation
}

您现在可以拥有多个 IPageRepository 实现并使用 Ninject 绑定适当的实现:

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

【讨论】:

  • 如果你能理解我的案例(语义上)需要什么,你能建议一个替代实现吗?
  • 如果你想继续沿着相同的路径,你可以创建一个IContentRepository&lt;Page&gt; 实现。我建议定义IPageRepository(可能实现IContentRepository&lt;Page&gt;)由实现它的XmlPageRepository 实现。
  • 我很难理解您的确切意思,因为您使用了实施和实施几次的词语。如果您可以澄清它或更好地修改我在您的答案中的代码到我可以想象您的意思的水平,我会接受您的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多