gpt4 book ai didi

c# - DryIoc - 使用 ID 注册多个实例

转载 作者:行者123 更新时间:2023-12-05 05:38:18 28 4
gpt4 key购买 nike

我想在容器中注册一个类的多个实例。每个实例都由其 ID 属性标识。

public interface MyInterface
{
string Id { get; }
}

public class MyImpl : MyInterface
{
public string Id { get; }
public MyImpl(string id) => Id = id;
}

而且,我想在另一个类的构造函数中接收这个实例。

using DryIoc;

public class User
{
public MyInterface Obj { get; }
public User(string id, Func<string, MyInterface> getObj)
=> Obj = getObj(id);
}

class Program
{
static void Main()
{
Container container = new();
container.RegisterInstance<MyInterface>(new MyImpl("A"), serviceKey: "A");
container.RegisterInstance<MyInterface>(new MyImpl("B"), serviceKey: "B");
container.Register<User>();
var user = container.Resolve<Func<string, User>>()("A");
}
}

此代码抛出 ContainerException。

DryIoc.ContainerException: code: Error.UnableToResolveFromRegisteredServices;
message: Unable to resolve MyInterface with passed arguments [String@0] (IsWrappedInFunc, IsDirectlyWrappedInFunc)
in wrapper Func<String, MyInterface> as parameter "getObj" WrapperExpressionFactoryWithSetup FactoryId=158 with passed arguments [String@0] (IsWrappedInFunc)
in User FactoryId=146 with passed arguments [String@0] (IsWrappedInFunc, IsDirectlyWrappedInFunc)
in resolution root wrapper System.Func`2[System.String,User] WrapperExpressionFactoryWithSetup FactoryId=158 with passed arguments [String@0]
from container without scope
with normal and dynamic registrations:
("B", {FactoryID=145, ImplType=MyImpl, Reuse=Singleton {Lifespan=1000}}) ("A", {FactoryID=144, ImplType=MyImpl, Reuse=Singleton {Lifespan=1000}})

可以通过在Container.Resolve()中指定serviceKey来获取想要的实例。但是,由于 User 类是通过构造函数注入(inject)到另一个实例中的,我们不想直接调用 Contaienr 的方法。

我认为我可以在 Register() 的参数中适本地指定 made。应该如何指定?

编辑

现在,创建一个对象容器并解决这个问题。

public static class Holder<T> where T : class
{
private static readonly Dictionary<string, T> _dictionary = new();
public static void Add(string id, T obj) => _dictionary.Add(id, obj);
public static void Remove(string id) => _dictionary.Remove(id);
public static T Get(string id) => _dictionary[id];
}

interface IService
{
string Id { get; }
}
class Service : IService
{
public string Id { get; }
public Service(string id) => Id = id;
}

interface IServiceUser
{
IService Service { get; }
}

class ServiceUser : IServiceUser
{
public IService Service { get; }
public ServiceUser(IService service) => Service = service;
}
class ViewModel
{
public ViewModel(IServiceUser serviceUser)
{
Console.WriteLine(serviceUser.Service.Id);
}
}

static class Program
{
static void Main()
{
Holder<IService>.Add("A", new Service("A"));
Holder<IService>.Add("B", new Service("B"));

Container container = new();
container.Register(made: Made.Of(() => Holder<IService>.Get(Arg.Of<string>())));
container.Register<IServiceUser, ServiceUser>();
container.Register<ViewModel>();

var createVm = container.Resolve<Func<string, ViewModel>>();
var vmA = createVm("A");
var vmB = createVm("B");
}
}

但是既然容器可以容纳对象,我在想,如果我能将Func中传递的值传递给serviceKey,就不需要Holder类了。

最佳答案

您可以替换 Func<string, MyInterface> getObjIEnumerable<KeyValuePair<<string, MyInterface>>> getObj因此它将作为字典来获取您的实例(DryIoc 目前不直接支持 Dictionary,但将来可能会支持)。

这里是完整的例子(https://dotnetfiddle.net/kxZCck):

using System;
using System.Collections.Generic;
using System.Linq;
using DryIoc;

public interface MyInterface
{
string Id { get; }
}

public class MyImpl : MyInterface
{
public string Id { get; }
public MyImpl(string id) => Id = id;
}

public class User
{
public MyInterface Obj { get; }
public User(string id, IEnumerable<KeyValuePair<string, MyInterface>> getObj)
=> Obj = getObj.First(kv => kv.Key == id).Value;
}

class Program
{
static void Main()
{
Container container = new();
container.RegisterInstance<MyInterface>(new MyImpl("A"), serviceKey: "A");
container.RegisterInstance<MyInterface>(new MyImpl("B"), serviceKey: "B");
container.Register<User>();
var user = container.Resolve<Func<string, User>>()("A");
Console.WriteLine(((MyImpl)user.Obj).Id);
}
}

这是要跟踪的词典功能问题:https://github.com/dadhi/DryIoc/issues/504

更新——没有Holder的解决方案

这是您不需要的解决方案 Holder并且不需要用字典 (https://dotnetfiddle.net/IAhGTg) 污染您的服务构造函数:

using System;
using System.Collections.Generic;
using DryIoc;

interface IService
{
string Id { get; }
}

class Service : IService
{
public string Id { get; }
public Service(string id) => Id = id;
}

interface IServiceUser
{
IService Service { get; }
}

class ServiceUser : IServiceUser
{
public IService Service { get; }
public ServiceUser(IService service) => Service = service;
}

class ViewModel
{
public ViewModel(IServiceUser serviceUser)
{
Console.WriteLine(serviceUser.Service.Id);
}
}

static class Program
{
static void Main()
{
var container = new Container();

container.RegisterInstance<IService>(new Service("A"), serviceKey: "A");
container.RegisterInstance<IService>(new Service("B"), serviceKey: "B");

// Register a delegate returning a service without key selecting the result
// from the collection of keyed services with their keys and using the key provided by Func<string,...>
container.RegisterDelegate<KeyValuePair<string, IService>[], string, IService>(
(services, serviceKey) => Array.Find(services, s => s.Key == serviceKey).Value
);

container.Register<IServiceUser, ServiceUser>();
container.Register<ViewModel>();

var createVm = container.Resolve<Func<string, ViewModel>>();
var vmA = createVm("A");
var vmB = createVm("B");
}
}

关于c# - DryIoc - 使用 ID 注册多个实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72959325/

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