Reputation: 12142
I'm faced with the prospect of using a factory method like below to effect setter based DI (because Entity Framework prevents me from using constructor based DI). So when an object is materialized in EF I call the method below to do the setter 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
}
I don't like this because it becomes a n-based problem whereby if I have 20 types that need this setter injection then whichever one is type checked in 20th place takes 20 times the amount of time to check as the first type check and since Im doing this every single time an object is materialized in EF it will likely not scale.
So Im looking for a better algorithm. The previous "solution" was to just assign the appropriate KeyHolder in the constructor of the associated object as below:
public FeeType()
{
this.KeyHolder = new FeeTypeKeyHolder();
}
This still seems like the most runtime efficient solution and one I'm still leaning very strongly towards regardless of testability due to potentially massive effect setter based DI will likely have with the above factory method. I'd really likely to decouple these classes but not at the expense of the scalability for this web application.
Upvotes: 0
Views: 34
Reputation: 3234
First of all, are you sure this is going to have such a bad performance impact. I would doubt so.
Anyway, you can use Visitor patter to implement double dispatch, so instead of 20 test for type of the object, you invoke 2 virtual methods, that is two lookups in virtual methods tables, which might be faster than 20 tests, however there is the overhead of two indirect function calls, stack frame allocation for each of them, etc. But again, do we really want to go so deep in case of a C# project with Entity Framework?
Example:
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());
}
You can also implement the lookup for the correct method based on type through hashing.
HashMap<Type, Action<BaseType>> actions;
actions.Add(typeof(FeeType), x => { ((FreeType)x).KeyHolder = new .... });
...
actions[ft.GetType()].Invoke(ft);
Upvotes: 1
Reputation: 7524
You can mark properties you need to set via DI with your attribute, like [Inject]
, and then in desired place (like constructor) call helper method like MyHelper.InjectProperties(this)
. In helper you can get attributes with [Inject] and resolve their values directly from constructor.
Most of IoC/DI frameworks supports property injection in a performance effective way, so in best of worlds you won't need to implement it by yourself.
Upvotes: 1