我面临使用如下工厂方法实现基于setter的DI的前景(因为实体框架阻止我使用基于构造函数的DI)。因此,当在EF中实现对象时,我调用下面的方法来执行设置器DI。
public void AttachKeyHolder(ILocalizableEntity localizableEntity)
{
var ft = (localizableEntity as FeeType);
if (ft != null)
{
localizableEntity.KeyHolder = new FeeTypeKeyHolder();
return;
}
var other = (localizableEntity as OtherType);
if (other != null)
{
localizableEntity.KeyHolder = new OtherTypeKeyHolder();
return;
}
// And on and on and on for every applicable type
}
我不喜欢这样,因为它变成了一个基于n的问题,如果我有20种类型需要这个定位器注入,那么在第20位进行类型检查的任何一种需要20倍的检查时间。第一次类型检查,因为我每次在EF中实现一个对象,它可能不会扩展。
所以我正在寻找更好的算法。之前的解决方案"只是在关联对象的构造函数中分配适当的KeyHolder,如下所示:
public FeeType()
{
this.KeyHolder = new FeeTypeKeyHolder();
}
这似乎仍然是运行时效率最高的解决方案,而且我仍然非常倾向于不论可测性,因为基于DI的潜在大规模效果设置器可能与上述工厂方法有关。我真的很可能将这些类解耦,但不会牺牲这个Web应用程序的可伸缩性。
答案 0 :(得分:1)
您可以使用您的属性标记需要通过DI设置的属性,例如[Inject]
,然后在所需的位置(如构造函数)调用辅助方法,如MyHelper.InjectProperties(this)
。在帮助器中,您可以使用[Inject]获取属性并直接从构造函数中解析它们的值。
大多数IoC / DI框架以性能有效的方式支持属性注入,因此在最好的世界中,您不需要自己实现它。
答案 1 :(得分:1)
首先,您确定这会对性能产生如此糟糕的影响吗?我会怀疑的。
无论如何,您可以使用Visitor模式实现双重调度,因此您可以调用2个虚拟方法,而不是20个对象类型的测试,即虚拟方法表中的两个查找,可能比20次测试要快,但是有两个间接函数调用的开销,每个调用的堆栈帧分配等等。但是,我们真的想在实体框架的C#项目中如此深入吗?
示例:
class Visitor {
public virtual void Visit(FeeType f) {}
public virtual void Visit(OtherType t) {}
}
class abstract BaseType { public abstract void Accept(Visitor v); }
class FeeType : BaseType {
public override void Accept(Visitor v) { v.Visit(this); }
}
class OtherType : BaseType {
public override void Accept(Visitor v) { v.Visit(this); }
}
class DIVisitor : Visitor {
public virtual void Visit(FeeType f) { f.KeyHolder = new ... }
public virtual void Visit(OtherType t) { t.KeyHolder = new ... }
}
public void AttachKeyHolder(ILocalizableEntity localizableEntity)
{
var ft = (localizableEntity as TypeBase);
ft.Accept(new DIVisitor());
}
您还可以通过散列实现基于类型的正确方法的查找。
HashMap<Type, Action<BaseType>> actions;
actions.Add(typeof(FeeType), x => { ((FreeType)x).KeyHolder = new .... });
...
actions[ft.GetType()].Invoke(ft);