Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/274.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 定制IoC-如何实现具有范围的DI?_C#_Dependency Injection_Inversion Of Control_Autofac - Fatal编程技术网

C# 定制IoC-如何实现具有范围的DI?

C# 定制IoC-如何实现具有范围的DI?,c#,dependency-injection,inversion-of-control,autofac,C#,Dependency Injection,Inversion Of Control,Autofac,我正在为自己的学习/成长编写一个IoC容器。通常我会写以下内容: using(DisposableObject dispObj = new DisposableObject()) { UserRepository users = new UserRepository(dispObj); // Do stuff with user. } 我们将转向: using(IDisposableObject dispObj = Container.Resolve<IDisposab

我正在为自己的学习/成长编写一个IoC容器。通常我会写以下内容:

using(DisposableObject dispObj = new DisposableObject())
{
    UserRepository users = new UserRepository(dispObj);

    // Do stuff with user.
}
我们将转向:

using(IDisposableObject dispObj = Container.Resolve<IDisposableObject>())
{
    IUserRepository users = Container.Resolve<IUserRepository>();

    // Do stuff with user.
}
使用(IDisposableObject dispObj=Container.Resolve())
{
IUserRepository users=Container.Resolve();
//和用户一起做事。
}
在使用IoC时,如何提取DisposableObject,使其成为使用范围的
中使用的唯一实例?我试图弄清楚Autofac是如何做到的,但我不完全确定


EDIT:当使用
作用域实例化对象时,所有解析该类型的调用(在本例中为
IDisposableObject
)都应返回作用域变量,而不是新实例。同样重要的是,在调用
using
语句和另一个
Resolve
之后,它返回一个新实例。

以这种方式使用一次性对象时,要记住的是容器中的引用也会被释放,因此,理想情况下,当您通过Resolve返回实例时,每次都需要返回一个新实例

您需要做的是,在向您的容器注册类型时,允许它指定共享(单例)或非共享的行为,例如:

Container.RegisterType<IDisposableObject>(CreationPolicy.NonShared);

using (var disposable = Container.Resolve<IDisposableObject>()) {

}
Container.RegisterType<IUserRepository>(CreationPolicy.Shared);

using (var disposable = Container.Resolve<IDisposableObject>()) {
    var userRepository = Container.Resolve<IUserRepository>();
    // only one instance of user repository is created and persisted by the container.
}

释放对象时,请确保它设置了IsDisposed属性。然后,您可以从容器中监视该属性吗?

您可以返回类型为
Owned
的对象,而不是
Foo

拥有的
可能如下所示:

public class Owned<T> : IDisposable
{
   private readonly Container container;
   private readonly T value;

   public Owned(Container container, T value)
   {
      this.container = container;
      this.value = value;
   }

   public T Value { get { return value; } }

   public void Dispose()
   {
      this.container.ReleaseOwned(this);
   }

}
拥有的公共类:IDisposable
{
专用只读容器;
私有只读T值;
公有(集装箱,T值)
{
this.container=容器;
这个值=值;
}
公共T值{get{return Value;}}
公共空间处置()
{
this.container.ReleaseOwned(this);
}
}
现在,客户机可以通过处理对象来通知容器已处理该对象,即使
Foo
本身不是一次性的。通过这种方式,容器知道何时清理对象及其依赖项(也可能是一次性的,但对客户端不可见),并且您可以实现所追求的行为


Autofac也做了类似的事情。请看,尼古拉斯·布卢姆哈特(Nicholas Blumhardt)在博客中介绍了这一概念。

这正是我想要的答案。我知道我需要通过某种“范围”。我只是想知道如果单件已被处理,如何从我的字典中删除它?我想到的一种方法是使用(var localContainer=IoC.Create())
为每个“scope”
创建一个新的容器,然后调用
localContainer.Resolve()
在本地进行解析……好吧,您不会处理单例,否则您将无法再次返回它们。如果您的容器有一个单例的内部哈希表,请将它们存储在可以轻松再次获取它们的位置。如果要解析的类型没有声明为Singleton,则只需通过Resolve返回它,而不存储它。使用带有一次性模式问题的容器并不是一个好办法,因为您每次都必须设置和创建容器……因此,如果您不处理单例,它们如何特定于使用
范围的
?哈希表中的键始终会命中同一个单例(已释放或未释放),因为它没有被删除。我认为您忽略了一个问题,即如果我在using语句中调用Container.Resolve(),它应该引用从
using
作用域创建的Container.Resolve()。Singleton被设计为单个实例。如果您处理了它们,它们就不能再使用了。这是因为你不会将它们与using块一起使用,而我仍然想知道的正是“对处置的监控”。我怎样才能继续监视某个东西,直到它被处理掉……昨晚我在看到你的帖子之前发现了同样的链接。唯一的问题是不是Resolve()然后返回Owned而不是t?那么,我的代码是否总是必须依赖于使用
语句的
中的Owned,然后使用Owned.Value来获取实际的t?调用代码知道它是否需要所有权,因此它可以根据需要调用
Resolve()
Resolve
。或者,如果您不喜欢根据请求的类型更改语义,您可以使用单独的
Resolve
ResolveOwned
方法。好吧,如果我真的需要一些无法通知它已被处置的方法,那么这很有意义。
Container.Register<IUserRepository, UserRepository>(CreationPolicy.SharedScope);
public interface IMonitoredDisposable : IDisposable
{
  bool IsDisposed { get; set; }
}
public class Owned<T> : IDisposable
{
   private readonly Container container;
   private readonly T value;

   public Owned(Container container, T value)
   {
      this.container = container;
      this.value = value;
   }

   public T Value { get { return value; } }

   public void Dispose()
   {
      this.container.ReleaseOwned(this);
   }

}