gpt4 book ai didi

c# - 与 StructureMap 4.6 transient 生命周期混淆

转载 作者:行者123 更新时间:2023-11-30 21:35:31 25 4
gpt4 key购买 nike

我正在使用 StructureMap 4.6 作为我的 IoC 容器。我对它的生命周期有点困惑。正如我在其文档中所读到的,Transient 将为每个容器创建一个对象实例。 Supported Lifecycles

我正在通过创建一个简单的控制台应用程序项目来检查这种情况。我的代码如下:

程序.cs

class Program
{
private static IContainer _Container;
static void Main(string[] args)
{
_Container = Container.For<ConsoleRegistry>();

var serv1 = _Container.GetInstance<IFileService>();
Console.WriteLine($"Name: {_Container.Name}");
Console.WriteLine(serv1.GetUniqueID());

var serv2 = _Container.GetInstance<IFileService>();
Console.WriteLine($"Name: {_Container.Name}");
Console.WriteLine(serv2.GetUniqueID());

Console.ReadKey();
}
}

ConsoleRegistry.cs

public class ConsoleRegistry : Registry
{
public ConsoleRegistry()
{
Scan(_ =>
{
_.TheCallingAssembly();
_.WithDefaultConventions();
});
}
}

IFileSerivce.cs

public interface IFileService
{
string Read(string path);

void Write(string path, string content);

bool FileExists(string path);

string GetUniqueID();
}

文件服务.cs

public class FileService : IFileService
{
private static int instanceCounter;
private readonly int instanceId;

public FileService()
{
this.instanceId = ++instanceCounter;
Console.WriteLine("File Service is Created.");
}

public int UniqueID
{
get { return this.instanceId; }
}

public string GetUniqueID()
{
return UniqueID.ToString();
}

public string Read(string path)
{
return File.ReadAllText(path);
}

public void Write(string path, string content)
{
File.WriteAllText(path, content);
}

public bool FileExists(string path)
{
return File.Exists(path);
}
}

当我运行应用程序时,结果是:

Output

我的问题是,当我解析 IFileService 实例时,我希望每个容器获得一个 FileService 实例。但是,如您所见,它给出了两个不同的实例。为什么会这样?

最佳答案

您对 documentation 的理解不正确。

  • Transient -- The default lifecycle. A new object is created for each logical request to resolve an object graph from the container.
  • Singleton -- Only one object instance will be created for the container and any children or nested containers created by that container

您正在使用 Transient,这意味着您每次 Resolve 被调用时都会得到一个实例。

但是您所描述的行为是针对Singleton 的,这意味着仅在第一次调用Resolve 时创建实例。。

要获得您想要的行为,您必须将注册类型更改为Singleton

public class ConsoleRegistry : Registry
{
public ConsoleRegistry()
{
Scan(_ =>
{
_.TheCallingAssembly();
_.With(new SingletonConvention<IFileService>());
_.WithDefaultConventions();
});
}
}

internal class SingletonConvention<TPluginFamily> : IRegistrationConvention
{
public void Process(Type type, Registry registry)
{
if (!type.IsConcrete() || !type.CanBeCreated() || !type.AllInterfaces().Contains(typeof(TPluginFamily))) return;

registry.For(typeof(TPluginFamily)).Singleton().Use(type);
}
}

引用:How can I configure Structuremap to auto scan type in Assembly and Cache by Singleton?

单例 VS transient 示例

考虑这一点的最简单方法是展示一个使用 DI 容器的示例。

服务

这里我们有一个服务和一个应用服务。这里唯一真正的区别是应用程序服务旨在成为整个应用程序图

public class Service
{
public string Name { get; private set; } = Guid.NewGuid().ToString();
}

public class Application
{
private readonly Service singleton;
private readonly Service transient;

public Application(Service singleton, Service transient)
{
this.singleton = singleton;
this.transient = transient;
}

public Service Singleton { get { return singleton; } }
public Service Transient { get { return transient; } }
}

容器

在我们的容器中,我们注册了 2 个 Service 实例,一个是单例,一个是 transient 。单例仅每个容器实例实例化一次每次调用 Resolve 时都会实例化 transient 。

public class MyContainer
{
private readonly Service singleton = new Service();

public Application Resolve()
{
return new Application(
singleton: this.singleton,
transient: new Service());
}
}

用法

在真实世界的应用程序中,只有一个 Application 实例。但是,我们展示了两个 Application 实例,以证明注册为 Singleton 的服务将是同一容器实例的同一实例。每次调用 Resolve 时都会创建一个 transient 。

class Program
{
static void Main(string[] args)
{
var container = new MyContainer();

var application1 = container.Resolve();
var application2 = container.Resolve();


Console.WriteLine($"application1.Transient.Name: {application1.Transient.Name}");
Console.WriteLine($"application2.Transient.Name: {application2.Transient.Name}");
Console.WriteLine();
Console.WriteLine($"application1.Singleton.Name: {application1.Singleton.Name}");
Console.WriteLine($"application2.Singleton.Name: {application2.Singleton.Name}");

Console.ReadKey();
}
}

输出

application1.Transient.Name: dc134d4d-75c8-4f6a-a1a5-367156506671application2.Transient.Name: f3012ea2-4955-4cfa-8257-8e03a00b1e99

application1.Singleton.Name: 86d06d7d-a611-4f57-be98-036464797a41application2.Singleton.Name: 86d06d7d-a611-4f57-be98-036464797a41

关于c# - 与 StructureMap 4.6 transient 生命周期混淆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49156716/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com