我认为如果没有完整的架构更改,这可能是不可能的,但我有类(插件),可以在运行时为用户公开可配置的选项。
程序启动,用户可以选择使用各种插件,用户面对可以为每个插件修改的选项,用户按下播放按钮,这些配置选项可以读取和关闭。
当用户选择他们想要使用的插件时,会创建该类的实例,以便它可以显示该插件的可用选项。显然在正常情况下,当实例化类时,会传入构造函数参数。在这种情况下,如果插件具有ILogger的构造函数参数,并且其具体类具有DirectoryPath的构造函数参数,但这只有在用户单击播放时才可读,我怎么能得到我的IOC容器传递给它?
public class MyPlugin
{
private ILogger Logger;
private Dictionary<string, object> Properties = new Dictionary<string, object>();
public MyPlugin(ILogger Logger)
{
this.Logger = Logger;
SetupProperties();
}
private SetupProperties()
{
Properties.Add("LogDirectory","Please enter a directory");
}
private void UserPressedPlay()
{
//We can now read the property values user has entered
//Now I want to instantiate FileLogger with the LogDirectory property
}
public DoSomething(string Data)
{
this.Logger.Write(Data);
}
}
public interface ILogger
{
void Write(string Data);
}
public FileLogger : ILogger
{
private string DirectoryPath;
public FileLogger(string Directory)
{
this.DirectoryPath = Directory;
}
public Write(string Data)
{
//Write to file
}
}
答案 0 :(得分:0)
您可以向DirectoryPath
添加FileLogger
媒体资源,稍后再进行初始化。
public FileLogger : ILogger
{
public string DirectoryPath { get; set; }
public Write(string Data)
{
if (DirectoryPath != null) {
// Write to file
}
}
}
答案 1 :(得分:0)
您可以使用Expression.New
使用上述参数动态创建/调用构造函数。
Func<String, FileLogger> func = GetConsturctor<String, FileLogger>(); // Cache it somewhere.
FileLogger logger = func(@"C:\Loggerpath\"); // instantiate
static Func<TArg, TRes> GetConsturctor<TArg, TRes>()
{
Type resultType = typeof(TRes);
Type argType = typeof(TArg);
Type[] argumentArray = new Type[] { argType };
ConstructorInfo constructor = resultType.GetConstructor(argumentArray);
ParameterExpression param = Expression.Parameter(argType);
Expression<Func<TArg, TRes>> result = Expression.Lambda<Func<TArg, TRes>>(
Expression.New(constructor, param), param);
return result.Compile();
}
答案 2 :(得分:0)
所以DI提供了很大的灵活性和较低的耦合,但通常没有必要。对于这种特殊情况,担心如何添加它可能是过度的。看来你在这里有一个GUI配置为匹配你用来配置它的FileLogger
类,所以这里的DI可能有点过分。你有这个插件今天使用的任何其他类型的ILogger
吗?如果是这样,工厂选项可能是一个好选择。我怀疑,基于提到的GUI,只有一种类型的记录器。在这种情况下,不要挂在这里使用DI。如果你想弄清楚如何测试MyPlugin
课程,并且不确定如何在没有DI的情况下这样做,那么请告诉我,我将扩展这个答案以展示如何完成它。
希望有所帮助!
布兰登
答案 3 :(得分:0)
你想要做的是传入ILogger工厂而不是实际的ILogger。然后可以使用用户的参数从UserPressedPlay调用工厂以创建实际的Logger实例。