DI dotnet/C#: 在构造函数中解析具有(不同)字符串的对象
DI dotnet/C#: Resolve objects with (different) strings in constructor
我有一个使用 Configuration、DependencyInjection 和 Hosting 的 .Net 控制台应用程序,我需要在其中创建多个对象,其中每个对象都不同,具体取决于传递的字符串。
class Program
{
static void Main(string[] args)
{
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", false)
.Build();
serviceCollection.AddSingleton<IMyService, MyService>();
serviceCollection.AddSingleton<IOtherService, OtherService>();
serviceCollection.AddTransient<IMyObject, MyObject>();
...
public class MyObject : IMyObject
{
public string _aString {get; set;}
public MyObject(string aString)
{
_aString = aString;
}
}
public class MyService : IMyService
{
private IMyObject _objectA;
private IMyObject _objectB;
private readonly IOtherService _otherService;
private readonly IOptions<FilePaths> _filePaths;
public MyService(IOtherService otherService, IOptions<FilePaths> filePaths)
{
_otherService = otherService;
// file path options contains 2 different file path strings
_filePaths = filePaths;
}
public void WorkWithObjects()
{
// Instantiate Objects depending on File Path Strings
// Do some work with my objects here
}
}
每个字符串都是定义对象的文件路径,但我在上面的示例中抽象了行为。
解决此问题的最佳方法是什么?我的设计正确吗?
我做了一些研究并尝试:
- 直接在 MyService 中实例化对象(这很糟糕,因为它违反了 DI)
- 创建一个 MyObjectFactory 作为服务并在那里直接实例化对象(但现在如果我要更改 MyObject 实现我需要更改 Factory 实现,所以这也违反了 DI?)
- 使用 ActivatorUtilities.CreateInstance() 但我找不到传递字符串参数的方法
- 从对象构造函数中取出字符串参数,放入一个方法中,我在实例化对象时调用该方法(但这似乎不太干净)
首先,无需在 DI 容器中注册 MyObject:serviceCollection.AddTransient<IMyObject, MyObject>();
因为您计划根据配置拥有多个 'MyObject' 实例。我假设您可以在配置中有多个文件路径。
引入单独的 IMyObjectsFactory
界面非常好并且不违反任何规则。工厂的唯一职责是创建 IMyObject
的实例。当 IMyObject
实现改变时改变工厂实现是完全没问题的。您将 MyObject
的创建抽象为工厂。
public interface IMyObjectsFactory
{
IEnumerable<IMyObject> Create();
}
public class MyObjectFactory : IMyObjectsFactory
{
private readonly IOptions<FilePaths> _filePaths;
public MyObjectFactory(IOptions<FilePaths> filePaths)
{
_filePaths = filePaths;
}
public IEnumerable<IMyObject> Create()
{
foreach(var path in _filePaths.Value.Paths)
{
yield return new MyObject(path)
}
}
}
我有一个使用 Configuration、DependencyInjection 和 Hosting 的 .Net 控制台应用程序,我需要在其中创建多个对象,其中每个对象都不同,具体取决于传递的字符串。
class Program
{
static void Main(string[] args)
{
var configuration = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", false)
.Build();
serviceCollection.AddSingleton<IMyService, MyService>();
serviceCollection.AddSingleton<IOtherService, OtherService>();
serviceCollection.AddTransient<IMyObject, MyObject>();
...
public class MyObject : IMyObject
{
public string _aString {get; set;}
public MyObject(string aString)
{
_aString = aString;
}
}
public class MyService : IMyService
{
private IMyObject _objectA;
private IMyObject _objectB;
private readonly IOtherService _otherService;
private readonly IOptions<FilePaths> _filePaths;
public MyService(IOtherService otherService, IOptions<FilePaths> filePaths)
{
_otherService = otherService;
// file path options contains 2 different file path strings
_filePaths = filePaths;
}
public void WorkWithObjects()
{
// Instantiate Objects depending on File Path Strings
// Do some work with my objects here
}
}
每个字符串都是定义对象的文件路径,但我在上面的示例中抽象了行为。
解决此问题的最佳方法是什么?我的设计正确吗?
我做了一些研究并尝试:
- 直接在 MyService 中实例化对象(这很糟糕,因为它违反了 DI)
- 创建一个 MyObjectFactory 作为服务并在那里直接实例化对象(但现在如果我要更改 MyObject 实现我需要更改 Factory 实现,所以这也违反了 DI?)
- 使用 ActivatorUtilities.CreateInstance() 但我找不到传递字符串参数的方法
- 从对象构造函数中取出字符串参数,放入一个方法中,我在实例化对象时调用该方法(但这似乎不太干净)
首先,无需在 DI 容器中注册 MyObject:serviceCollection.AddTransient<IMyObject, MyObject>();
因为您计划根据配置拥有多个 'MyObject' 实例。我假设您可以在配置中有多个文件路径。
引入单独的 IMyObjectsFactory
界面非常好并且不违反任何规则。工厂的唯一职责是创建 IMyObject
的实例。当 IMyObject
实现改变时改变工厂实现是完全没问题的。您将 MyObject
的创建抽象为工厂。
public interface IMyObjectsFactory
{
IEnumerable<IMyObject> Create();
}
public class MyObjectFactory : IMyObjectsFactory
{
private readonly IOptions<FilePaths> _filePaths;
public MyObjectFactory(IOptions<FilePaths> filePaths)
{
_filePaths = filePaths;
}
public IEnumerable<IMyObject> Create()
{
foreach(var path in _filePaths.Value.Paths)
{
yield return new MyObject(path)
}
}
}