懒惰加载集合 - 如何获取项目?

Mic*_*tum 7 .net architecture ninject

我有一个简单的Class,它只是一个简单的POCO - 它只保存数据.有一个例外:它包含一个Notes集合.我想延迟加载此集合,以便我不必获取不需要它们的页面上的Notes.这个存根是这样的:

public class MyDTOClass 
{
    private ICollection<Note> _notes = null;

    public ICollection<Note> Notes
    {
        get
        {
            if(_notes == null)
            {
                // Get an INoteRepository and initialize the collection
            }
            return _notes;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,我想知道如何从这里开始.它是一个ASP.net MVC应用程序,我使用依赖注入将IRepositories注入需要它们的类中,例如我的控制器.但是由于这里的这个类应该是一个非常简单的DTO,我不愿意在其中注入一个INoteRepository,也因为调用者不应该担心或关心这是一个懒惰的事实.

所以我想在我的模型中拥有另一个包含INoteRepository的类.

public class MyDataAccessClass
{
    private INoteRepository _noteRepo;

    // Inject is part of Ninject and makes sure I pass the correct
    // INoteRepository automatically
    [Inject]
    public MyDataAccessClass(INoteRepository noteRepository)
    {
        _noteRepo = noteRepository;
    }

    public IEnumerable<Note> GetNotes(int projectId)
    {
        return _noteRepo.GetNotes(projectId);
    }
}
Run Code Online (Sandbox Code Playgroud)

这当然会工作,但我想知道这是否是正确的架构?我将简单的DTOClass耦合到另一个数据访问类,也可能耦合到我的DI机制(因为我需要在Notes的getter中创建一个Data Access类的实例).

你会以不同的方式做吗?有没有更好的方法来做到这一点,还记住我已经使用Ninject?

我猜这不再是POCO或DTO,因为它现在包含逻辑,但没关系.我希望它看起来像外部调用者的POCO所以我喜欢在这个或其他类上有一个属性"Notes"而不是像"GetNotesForProject"这样的方法.

我当前的解决方案非常难看,因为我需要从我的MvcApplication获取Ninject内核并使用它来启动ProjectDataProvider类,该类在其构造函数中使用INoteRepository,以避免将INoteRepository放在我的"DTO"类中的某处:

public ICollection<Note> Notes
{
    get
    {
        if(_notes == null)
        {
            var app = HttpContext.Current.ApplicationInstance as MvcApplication;
            if (app == null)
             throw new InvalidOperationException("Application couldn't be found");
            var pdp = app.Kernel.Get<ProjectDataProvider>();
            _notes = new List<Note>(pdp.GetNotes(Id));
        }
        return _notes;
    }
}
Run Code Online (Sandbox Code Playgroud)

编辑:打开赏金.让我们忽略"POCO"和"DTO"的术语,我会相应地重构.所以这是关于:在这种情况下,Lazy-Loading代码应该如何看待,是否可以/我应该避免将INoteRepository传递给MyDTOClass?

mad*_*ode 8

您的DTO不需要知道存储库本身.它所需要的只是一个代表,可以为它提供笔记的价值.

这样的事情怎么样:

public class MyDTOClass
{
    private ICollection<Note> _notes = null;

    public ICollection<Note> Notes
    {
        get
        {
            if (_notes == null)
            {
                if (notesValueProvider == null)
                    throw new InvalidOperationException("ValueProvider for notes is invalid");
                _notes = notesValueProvider();
            }
            return _notes;
        }
    }

    private Func<ICollection<Note>> notesValueProvider = null;

    public MyDTOClass(Func<ICollection<Note>> valueProvider)
    {
        notesValueProvider = valueProvider;
    }
}
Run Code Online (Sandbox Code Playgroud)

根据定义,您的存储库应该为您提供DTO的实例,我们应该能够传递值提供程序委托,如下所示:

public class Repository
{
    public MyDTOClass GetData()
    {
        MyDTOClass dto = new MyDTOClass(FetchNotes);
        return dto;
    }

    public ICollection<Note> FetchNotes()
    {
        return new List<Note>(200);
    }
}
Run Code Online (Sandbox Code Playgroud)

这对你有用吗?


小智 7

如果你可以等待.Net 4(即你尚未投入生产),Lazy(of T)是.Net框架中新的延迟加载功能. http://msdn.microsoft.com/en-us/library/dd642331(VS.100).aspx