延迟加载与Ninject [英] Lazy Loading with Ninject

查看:159
本文介绍了延迟加载与Ninject的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我评估ninject2,但似乎无法弄清楚如何做延迟加载等不是通过内核。

I'm evaluating ninject2 but can't seem to figure out how to do lazy loading other than through the kernel.

这是我所看到的那种失败的使用[注入]的目的属性。 是否有可能使用InjectAttribute但偷懒装?我讨厌我的每一个实例化对象的时候,迫使对象图的完整结构。

From what I can see that kind of defeats the purpose of using the [Inject] attributes. Is it possible to use the InjectAttribute but get lazy loading? I'd hate to force complete construction of an object graph every time I instantiated an object.

要指定,我真的只是好奇的性能。

To specify, I'm really just curious about the performance.

推荐答案

更新:之前,.NET Framework 4的发布(连同懒℃将写我原来的答复; T> ),而其他的答案,而略多了最新的,还是有点过时了。我要离开我原来的答复在以下情况下,任何人被卡在一个较旧的版本,但不会建议其与Ninject或.NET的最新版本使用。

Update: My original answer was written before the .NET Framework 4 was released (along with Lazy<T>), and the other answer, while slightly more up-to-date, is still a bit obsolete now. I'm leaving my original answer below in case anybody is stuck on an older version, but wouldn't advise its use with the latest version of Ninject or .NET.

在Ninject 厂扩建是这样做的现代生活方式。它会自动连线了任何参数或属性。你并不需要一个单独的此绑定 - 刚刚成立的服务,以通常的方式和扩展处理剩下的

The Ninject Factory Extension is the modern way of doing this. It will automatically wire up any arguments or properties. You don't need a separate binding for this - just set up your services in the usual way and the extension handles the rest.

仅供参考,相同的扩展也可以线自定义工厂接口,或 Func键&LT; T&GT; 参数。与这些不同的是,他们将每一次创建一个新的实例,所以它实际上是一个工厂,不只是懒惰的实例。只是指出这一点,因为文件是不完全清楚的。

FYI, the same extension can also wire up custom factory interfaces, or Func<T> arguments. The difference with these is that they'll create a new instance every time, so it's actually a factory, not just lazy instantiation. Just pointing this because the documentation isn't totally clear about it.

作为一项规则,对象图的完整结构不应该是昂贵的,如果一个类被注入了依赖性,它可能无法使用,它可能是一个很好的迹象,表明类有太多的责任。

As a rule, "complete construction of an object graph" shouldn't be that expensive, and if a class is being injected with dependencies that it may not use, it's probably a good sign that the class has too many responsibilities.

这是不是真的Ninject本身的限制 - 如果你想想看,这不是真的有可能有一个懒惰依赖,除非是(a)被注入的依赖本身就是一个懒惰的装载机,如 延迟&LT; T&GT; 类.NET 4,或(b)所有依赖的属性和方法的使用延迟实例化。 的东西的已经在里面被注入。

This isn't really a limitation of Ninject per se - if you think about it, it's not really possible to have a "lazy dependency" unless either (a) the dependency being injected is itself a lazy loader, such as the Lazy<T> class in .NET 4, or (b) all of the dependency's properties and methods use lazy instantiation. Something has to be injected in there.

您可以完成(一)相对容易地通过使用的提供者接口的方法结合的(编辑:Ninject不支持开放的仿制药与供应商绑定)的和有约束力的开放式泛型类型。假设你没有.NET 4中,你必须创建接口和实现自己的:

You could accomplish (a) relatively easily by using the provider interface a method binding (ed: Ninject doesn't support open generics with provider bindings) and binding an open generic type. Assuming you don't have .NET 4, you would have to create the interface and implementation yourself:

public interface ILazy<T>
{
    T Value { get; }
}

public class LazyLoader<T> : ILazy<T>
{
    private bool isLoaded = false;
    private T instance;
    private Func<T> loader;

    public LazyLoader(Func<T> loader)
    {
        if (loader == null)
            throw new ArgumentNullException("loader");
        this.loader = loader;
    }

    public T Value
    {
        get
        {
            if (!isLoaded)
            {
                instance = loader();
                isLoaded = true;
            }
            return instance;
        }
    }
}

然后你可以绑定整个懒接口 - 所以只是绑定接口正常:

Then you can bind the entire lazy interface - so just bind the interfaces as normal:

Bind<ISomeService>().To<SomeService>();
Bind<IOtherService>().To<OtherService>();

和使用开放式泛型的lambda方法绑定懒接口:

And bind the lazy interface using open generics to a lambda method:

Bind(typeof(ILazy<>)).ToMethod(ctx =>
{
    var targetType = typeof(LazyLoader<>).MakeGenericType(ctx.GenericArguments);
    return ctx.Kernel.Get(targetType);
});

在此之后,可以引入懒惰依赖参数/属性:

After that, you can introduce lazy dependency arguments/properties:

public class MyClass
{
    [Inject]
    public MyClass(ILazy<ISomeService> lazyService) { ... }
}

这不会使的全部的操作懒 - Ninject仍然要真正创建一个实例 LazyLoader ,但是任何的第二级的相关性 ISomeService 将不会被载入直到 MyClass的检查中的 lazyService

This won't make the entire operation lazy - Ninject will still have to actually create an instance of the LazyLoader, but any second-level dependencies of ISomeService won't be loaded until MyClass checks the Value of that lazyService.

最明显的缺点是, ILazy&LT; T&GT; 不执行 T 本身,因此 MyClass的已实际被写入接受懒惰依赖关系,如果你想延迟加载的好处。然而,如果这是非常昂贵的创建一些特别的依赖,这将是一个不错的选择。我是pretty的相信你也会有这样的问题的任意的形式的DI,任何库。

The obvious downside is that ILazy<T> does not implement T itself, so MyClass has to actually be written to accept lazy dependencies if you want the benefit of lazy loading. Nevertheless, if it's extremely expensive to create some particular dependency, this would be a good option. I'm pretty sure you'll have this issue with any form of DI, any library.

据我所知,只有这样才能做到(B),而无需编写code山是使用一个代理生成类似的城堡DynamicProxy ,或者使用的 Ninject拦截扩展的。这将是pretty的复杂,我不认为你想要走这条路线,除非你不得不这样做。

As far as I know, the only way to do (b) without writing mountains of code would be to use a proxy generator like Castle DynamicProxy, or register a dynamic interceptor using the Ninject Interception Extension. This would be pretty complicated and I don't think you'd want to go this route unless you have to.

这篇关于延迟加载与Ninject的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆