带接口的 Ninject 和存储库模式

发布于 2024-09-07 07:55:54 字数 2430 浏览 1 评论 0原文

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

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

global.asax.cs 中的内容特定存储库

public class XmlPagesRepository : XmlRepository<Page> { }

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

This is the interfaces/class structure I have now:

BaseContentObject abstract class

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

Page concrete class

public class Page : BaseContentObject
{
...
}

Repository interface

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

Common interface implementation (for all content classes that inherit BaseContentObject class)

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

Content specific repository

public class XmlPagesRepository : XmlRepository<Page> { }

Ninject rule in global.asax.cs

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

that gives the following compile time error:

*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>'.*

I've spent quite some time figuring out my classes and interfaces structure to support my business needs. Now I don't know how to get past that Ninject error.

I want to use this structure in ASP.NET MVC controllers like this:

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

新一帅帅 2024-09-14 07:55:54

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

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

编辑:再看一下,转换是不可能的。 XmlRepository 实现 IContentRepository 而不是 IContentRepository。 Page 是 BaseContentObject 并不重要,转换是不可能的。这不会按您的预期工作。

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

public interface IPageRepository : IContentRepository<Page>
{
}

public interface XmlPageRepository : IPageRepository
{
    // implementation
}

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

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

I think if you create a test case using the concrete classes you'll find that indeed you can't implicitly convert from XmlPagesRepository to IContentRepository<Page>. It's hard to follow, but if that conversion is possible then I think bind it using ToMethod:

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

Edit: In looking at this some more, the conversion isn't possible. XmlRepository<Page> implementsIContentRepository<BaseContentObject> not IContentRepository<Page>. It doesn't matter that Page is a BaseContentObject, the cast isn't possible. This isn't going to work as you intended.

Edit2: "Implement" refers to implementing an interface; you implement an interface and inherit from (or extend) a class. Without fully understanding what you're trying to do, this is how I would design the repositories:

public interface IPageRepository : IContentRepository<Page>
{
}

public interface XmlPageRepository : IPageRepository
{
    // implementation
}

You can now have multiple implementations of IPageRepository and bind the appropriate one using Ninject:

Bind<IPageRepository>().To<XmlPageRepository>();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文