有效地确定类型

时间:2014-06-22 07:21:11

标签: c# algorithm type-conversion

我面临使用如下工厂方法实现基于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应用程序的可伸缩性。

2 个答案:

答案 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);