C# 减少不断增加的构造函数服务参数
我对使用Autofac还是一个新手,我对我正在使用的构造函数注入方法感到困扰。以下是场景: 我目前有两个类继承了IForms接口。每个类都有自己的接口C# 减少不断增加的构造函数服务参数,c#,dependency-injection,autofac,autofac-configuration,C#,Dependency Injection,Autofac,Autofac Configuration,我对使用Autofac还是一个新手,我对我正在使用的构造函数注入方法感到困扰。以下是场景: 我目前有两个类继承了IForms接口。每个类都有自己的接口 public interface IForms { long CreateNewForm(FormData data); FormData RetrieveFormById(long id); } public interface IFormA : IForms { } public interface IFormB : I
public interface IForms
{
long CreateNewForm(FormData data);
FormData RetrieveFormById(long id);
}
public interface IFormA : IForms
{ }
public interface IFormB : IForms
{ }
现在我有一个类来处理这个问题,如下所示:
public class ApplicationForms : IApplicationForms
{
private readonly IFormA _formA;
private readonly IFormB _formB;
public ApplicationForms(IFormA formA, IFormB formB)
{
_formA = formA;
_formB = formB;
}
public void SubmitApplicationForm(FormData data)
{
switch(data.FormType)
{
case FormType.FormA:
_formA.CreateNewForm(data);
break;
case FormType.FormB:
_formB.CreateNewForm(data);
break;
}
}
}
public class ApplicationForms : IApplicationForms
{
private readonly GetFormByTypeFunction _getFormByType;
public ApplicationForms(GetFormByTypeFunction getFormByType)
{
_getFormByType = getFormByType;
}
public void SubmitApplicationForm(FormData data)
{
var form = _getFormByType(data.FormType);
form.CreateNewForm(data);
}
}
builder.Register<GetFormByTypeFunction>(context => formType =>
{
switch (formType)
{
case FormType.Type1:
{
return context.Resolve<FormOne>();
}
case FormType.Type2:
{
return context.Resolve<FormTwo>();
}
default:
throw new InvalidOperationException("Unknown form type");
}
});
现在有可能会有另外两种形式,比如FormC,FormD,FormE。这里将要发生的是ApplicationForms构造函数中还有3个构造函数参数
有没有办法将所有构造函数参数组合成一个参数?我可以看出,它最终肯定会看起来很难看。因为有一个通用的IForms接口,所以您可以插入一个枚举
这看起来是战略模式的一个很好的候选者
我建议重构基本接口,以便能够识别它是什么类型的表单
public interface IForms {
FormType FormType { get; }
long CreateNewForm(FormData data);
FormData RetrieveFormById(long id);
}
并更新依赖类
public class ApplicationForms : IApplicationForms {
private readonly IEnumerable<IForms> forms;
public ApplicationForms(IEnumerable<IForms> forms) {
this.forms = forms;
}
public void SubmitApplicationForm(FormData data) {
var form = forms.FirstOrDefault(_ => _.FormType == data.FormType);
if(form != null)
form.CreateNewForm(data);
//...
}
}
现在,无论添加了多少表单,该类都可以执行而无需修改。您描述的问题是,您有许多表单,但在运行时需要一个特定的表单,因此您不希望注入所有表单。对于抽象工厂来说,这可能是一个很好的场景 我们通常使用单个方法将工厂表示为接口,但也可以使用委托:
public delegate IForm GetFormByTypeFunction(FormType formType);
现在,您的类如下所示:
public class ApplicationForms : IApplicationForms
{
private readonly IFormA _formA;
private readonly IFormB _formB;
public ApplicationForms(IFormA formA, IFormB formB)
{
_formA = formA;
_formB = formB;
}
public void SubmitApplicationForm(FormData data)
{
switch(data.FormType)
{
case FormType.FormA:
_formA.CreateNewForm(data);
break;
case FormType.FormB:
_formB.CreateNewForm(data);
break;
}
}
}
public class ApplicationForms : IApplicationForms
{
private readonly GetFormByTypeFunction _getFormByType;
public ApplicationForms(GetFormByTypeFunction getFormByType)
{
_getFormByType = getFormByType;
}
public void SubmitApplicationForm(FormData data)
{
var form = _getFormByType(data.FormType);
form.CreateNewForm(data);
}
}
builder.Register<GetFormByTypeFunction>(context => formType =>
{
switch (formType)
{
case FormType.Type1:
{
return context.Resolve<FormOne>();
}
case FormType.Type2:
{
return context.Resolve<FormTwo>();
}
default:
throw new InvalidOperationException("Unknown form type");
}
});
现在的问题是如何实施工厂。它可能仍然有一个switch语句或一些看起来不太优雅的语句,但这没关系。工厂的要点是,不管它如何工作,创建和/或选择实现的业务都会从依赖于实现的类中移出
您可以像这样向Autofac注册代理:
public class ApplicationForms : IApplicationForms
{
private readonly IFormA _formA;
private readonly IFormB _formB;
public ApplicationForms(IFormA formA, IFormB formB)
{
_formA = formA;
_formB = formB;
}
public void SubmitApplicationForm(FormData data)
{
switch(data.FormType)
{
case FormType.FormA:
_formA.CreateNewForm(data);
break;
case FormType.FormB:
_formB.CreateNewForm(data);
break;
}
}
}
public class ApplicationForms : IApplicationForms
{
private readonly GetFormByTypeFunction _getFormByType;
public ApplicationForms(GetFormByTypeFunction getFormByType)
{
_getFormByType = getFormByType;
}
public void SubmitApplicationForm(FormData data)
{
var form = _getFormByType(data.FormType);
form.CreateNewForm(data);
}
}
builder.Register<GetFormByTypeFunction>(context => formType =>
{
switch (formType)
{
case FormType.Type1:
{
return context.Resolve<FormOne>();
}
case FormType.Type2:
{
return context.Resolve<FormTwo>();
}
default:
throw new InvalidOperationException("Unknown form type");
}
});
我喜欢工厂代表的想法。省去了初始化所有实现的麻烦。很好。如果我注入所有表单,会有任何性能影响或暗示吗?我也想了解这一点。如果只需要一个实例,那么注入所有实例可能效率较低,但如果每次都不创建新实例,则效率会降低。即使您正在创建新实例,我也不会太担心性能。如果您将它们全部注入,则意味着您的类依赖于它们。但你不需要所有这些,你需要一个基于论点的。如果你按照类的需要和行为来建模,就会更清楚。另外,如果另一个类需要相同的行为,您不想复制逻辑。@Musikero31如果您真正需要的只是一个基于条件的实现,我建议使用这种方法来解决所有注入实现。即使FormType来自客户端?此外,注册来自Global.asax。所以我不知道结果会怎样。