5

These days I'm facing this situation often and I'm looking for an elegant solution. I have :

public abstract class TypeA 
{ 
    public abstract void AbtractMethod(IDependency dependency);
}

public class TypeB : TypeA
{
    public override void AbtractMethod(ISpecializedDependencyForB dependency) { }
}

public class TypeC : TypeA
{
    public override void AbtractMethod(ISpecializedDependencyForC dependency) { }
}

public interface IDependency { }
public interface ISpecializedDependencyForB : IDependency { }
public interface ISpecializedDependencyForC : IDependency { }

My objective is to make things transparent in the client perspective and to consume this code like that :

TypeA myDomainObject = database.TypeARepository.GetById(id); // The important point here is that I don't know if the object is of TypeB or TypeC when I consume it.
IDependency dependency = ? // How do I get the right dependency 
myDomainObject.AbtractMethod(dependency);

So the thing is that since I don't know the concrete type of the object, I can't inject the right dependency into it.

What I'm currently doing is that I create an abstract factory, to inject the right properties. I have two problems with that, the first one is that I would end up with a lot of factories. The second one is that it makes polymorphism useless since the client actually needs to care about "managing" the underlying type (I need to inject all the possible dependencies in the factory, and to instantiate the factory on the client code).

1) Therefore I was thinking of using property injection with unity, but I can't find out if it's possible to resolve the dependencies of an object, after it's been instanciated manually. Even with this approach I think I could still meet the same problem : I'm not sure if unity would check the actual type of the object and resolve the right dependency if a syntax like this existed :

 unityContainer.Resolve<TypeA>(myDomainObject) 

If not, I would need to know the type in advance and would be back to the same problem.

2) I have found this article mentionning that EF provides some mechanism for DI, but it seems that it is only meant to inject the framework services (PluralizationService, etc...). Otherwise it would have been a nice way to achieve that.

3) I could also not use DI in this case... It looks like by concept DI does not fit well with polymorphism. I'm not excited by this idea though.

I'd be happy to have a solution for the property injection I'm trying to achieve, or an idea of pattern I could use. However I really don't want to create a big infrastructure and obfuscate my code just for this purpose.

Note : I don't want to you use domain events in this case.

Thank you

tobiak777
  • 3,175
  • 1
  • 32
  • 44
  • You won't be able to override if the method signatures differ (and base method must be virtual). At the same time, if the subclass dependencies are for different interfaces, there should be no problem configuring these in the container? – StuartLC Mar 24 '15 at 13:08
  • Oh yes you're right, I forgot that when I was writing the example. But Actually it's alright, it definetely won't compile but it points to the behaviour I'm trying to accomplish. There is a problem because I will need to pass the right parameter manually based on the class type, it breaks the abstraction I'm trying to achieve with polymorphism – tobiak777 Mar 24 '15 at 13:14
  • Maybe I'm missing something but why can't you just check the type of myDomainObject using the "is" operator? – Tim Rutter Mar 24 '15 at 13:15
  • I agree I checked in vs and it doesnt like your overrides. however I think I understand what you mean. have you looked at named dependancies? – Ewan Mar 24 '15 at 13:16
  • http://stackoverflow.com/questions/7046779/with-unity-how-do-i-inject-a-named-dependency-into-a-constructor – Ewan Mar 24 '15 at 13:17
  • @afrogonabike I can, that's what I'm doing in my current solution (I hide it in some middleman class) but I don't want to. Polymorphism was meant to hide these details to the consumer code – tobiak777 Mar 24 '15 at 13:17
  • and I agree you can't override like you're trying to do. It has to match the signature so you'll have to pass in an IDependency in each case and cast that. – Tim Rutter Mar 24 '15 at 13:17
  • an alternate solution to named dependencies is to inject ALL the dependencies ie. AbtractMethod(List) then merge your typeA and typeB so you dont need two types – Ewan Mar 24 '15 at 13:19
  • Could you add a method to TypeA such as Type GetDependencyType() which returns the expected dependency type and is overriden in each sub class? – Tim Rutter Mar 24 '15 at 13:19
  • Well if you like it I'll add it as an answer :) – Tim Rutter Mar 24 '15 at 13:22
  • @afrogonabike actually it's not solving anything, I'm back with my situation where the client needs to figure out what to do based on the class type. What you sugget is just a variation of using the IS keyword, or perhaps I missed something ? – tobiak777 Mar 24 '15 at 13:35
  • Related: https://stackoverflow.com/questions/20035810/should-domain-objects-have-dependencies-injected-into-them – Steven Mar 24 '15 at 13:37
  • @Ewan Thanks but I am aware of that, actually in my question I'm asking for a way to resolve an object after it's been created manually because I won't be creating the object with Unity on the first hand. It will come from a repository. – tobiak777 Mar 24 '15 at 13:38
  • So you don't want to know anything about the type of the object returned nor the type of the dependency you need to pass in? Where are you dependencies defined? I've done this before where you have a callback that from the unknown object that requests a dependency - each dependency has a unique way of identifying it. – Tim Rutter Mar 24 '15 at 13:39
  • @Steven Thank you Steven, so do you advise putting these methods in an other class ? I think I would only be moving the problem by doing so or even creating new ones because what I'm injecting are domain services. I have no choice because these services will make calls to external APIs, I think you agree that I can't implement these calls in the domain model layer – tobiak777 Mar 24 '15 at 13:42
  • @red2nb: I would advice not doing constructor and property injection into entities and solely use method injection. Entities are short-lived objects and your container should not build them. So don't do `Resolve` but injecting dependencies into an entity's method (as you do with `AbtractMethod` is fine though). – Steven Mar 24 '15 at 13:46
  • @Steven I see and I totally share your view. But then I'm still with the problem I'm trying to solve. The only reason I was considering property injection is that I have troubles to find a way to inject the right dependency in a polymorphic situation, without introducing factories, mediators, or other middlemen at every call. Relying on the name of the class being used seemed to be a workaround – tobiak777 Mar 24 '15 at 13:49
  • @afrogonabike Yes this is what I'm trying to achieve. I'm not looking for magic, but at least for a way to configure this behaviour with an Ioc Container – tobiak777 Mar 24 '15 at 13:51
  • Discussions around DI and design tend to be very context dependent so in many cases a general solution can't be given to a general problem. I think this also holds in your case. Could you update your question with the specific class names and interface names for your use case? This might clear things up a bit and might allow us to feedback on your design (which is what you are after, if I'm not mistaken). – Steven Mar 24 '15 at 14:11
  • 1
    Ok where do the dependency objects exist? Something must know about them. I think i'm basically agreeing with Steven on this one - we need a bit more context as this may not be a generic scenario – Tim Rutter Mar 24 '15 at 14:12
  • @red2nb I've changed my answer with a possible solution – Tim Rutter Mar 24 '15 at 14:18

4 Answers4

6

TL;DR
Replace the IDependency parameter of the polymorphic AbstractMethod with an implementation-specific construction dependency parameter, which is injected by the IoC container, not by the consumer.

In more detail

The original class hierarchy will need to look like more like this for inheritance polymorphicism to work, as the superclass virtual method and subclass override methods must match signatures:

public abstract class TypeA // superclass
{ 
    public abstract void AbtractMethod(IDependency dependency);
}

public class TypeB : TypeA // subclass 1
{
    public override void AbtractMethod(IDependency dependency) 
    {
        Contract.Requires(dependency is ISpecializedDependencyForB);
        // ...
    } 
}

public class TypeC : TypeA // subclass 2
{
    public override void AbtractMethod(IDependency dependency)
    {
        Contract.Requires(dependency is ISpecializedDependencyForC)
        // ...
    } 
}

However, some things don't ring true with this design:

  • The LSP appears to be violated, since the although AbtractMethod() advertises that it accepts the base IDependency interface, the two subclasses actually depend on a specialized subclassed dependency.
  • It is also unusual, and arguably inconvenient, for a caller of these methods to build up the correct dependency and pass it to the method in order for it to be invoked correctly.

So, if possible, I would adopt a more conventional approach to the arrangement of dependencies, whereby the dependency is passed to the subclass constructor, and will be available to the polymorphic method when needed. This decouples the need to supply the appropriate IDependency to the method. Leave it to the IoC container to do the appropriate dependency resolution:

  • Use constructor injection to create the correct dependency into Classes TypeB and TypeC
  • If there is a secondary requirement to Expose an IDependency on the base class TypeA to consumers, then add an additional abstract property to TypeA of type IDependency (but this seems iffy)
  • As per Ewan's observation, the repository would need some kind of strategy pattern in order to serve up polymorphic domain entities (B or C). In which case, couple the repository to a factory to do exactly this. The concrete factory would need to be bound to the container in order to tap into Resolve().

So putting this all together, you might wind up with something like this:

using System;
using System.Diagnostics;
using Microsoft.Practices.Unity;

namespace SO29233419
{
    public interface IDependency { }
    public interface ISpecializedDependencyForB : IDependency { }
    public interface ISpecializedDependencyForC : IDependency { }

    public class ConcreteDependencyForB : ISpecializedDependencyForB {};
    public class ConcreteDependencyForC : ISpecializedDependencyForC { };

    public abstract class TypeA
    {
        // Your polymorphic method
        public abstract void AbtractMethod();
        // Only exposing this for the purpose of demonstration
        public abstract IDependency Dependency { get; }
    }
    public class TypeB : TypeA
    {
        private readonly ISpecializedDependencyForB _dependency;
        public TypeB(ISpecializedDependencyForB dependency)
        {
            _dependency = dependency;
        }
        public override void AbtractMethod()
        {
           // Do stuff with ISpecializedDependencyForB without leaking the dependency to the caller
        }
        // You hopefully won't need this prop
        public override IDependency Dependency
        {
            get { return _dependency; }
        }
    }

    public class TypeC : TypeA
    {
        private readonly ISpecializedDependencyForC _dependency;
        public TypeC(ISpecializedDependencyForC dependency)
        {
            _dependency = dependency;
        }
        public override void AbtractMethod()
        {
           // Do stuff with ISpecializedDependencyForC without leaking the dependency to the caller
        }
        public override IDependency Dependency
        {
            get { return _dependency; }
        }
    }

    public interface ITypeAFactory
    {
        TypeA CreateInstance(Type typeOfA);
    }
    public class ConcreteTypeAFactory : ITypeAFactory
    {
        private readonly IUnityContainer _container;
        public ConcreteTypeAFactory(IUnityContainer container)
        {
            _container = container;
        }
        public TypeA CreateInstance(Type typeOfA)
        {
            return _container.Resolve(typeOfA) as TypeA;
        }
    }

    public class TypeARepository
    {
        private readonly ITypeAFactory _factory;
        public TypeARepository(ITypeAFactory factory)
        {
            _factory = factory;
        }
        public TypeA GetById(int id)
        {
            // As per Ewan, some kind of Strategy Pattern.
            // e.g. fetching a record from a database and use a discriminating column etc.
            return (id%2 == 0)
                ? _factory.CreateInstance(typeof (TypeB))
                : _factory.CreateInstance(typeof (TypeC));
            // Set the properties of the TypeA from the database after creation?
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            // Unity Bootstrapping
            var myContainer = new UnityContainer();
            myContainer.RegisterType<ISpecializedDependencyForB, ConcreteDependencyForB>();
            myContainer.RegisterType<ISpecializedDependencyForC, ConcreteDependencyForC>();
            myContainer.RegisterType(typeof(TypeB));
            myContainer.RegisterType(typeof(TypeC));
            var factory = new ConcreteTypeAFactory(myContainer);
            myContainer.RegisterInstance(factory);
            myContainer.RegisterType<TypeARepository>(new InjectionFactory(c => new TypeARepository(factory)));

            // And finally, your client code.
            // Obviously your actual client would use Dependency Injection, not Service Location
            var repository = myContainer.Resolve<TypeARepository>();

            var evenNumberIsB = repository.GetById(100);
            Debug.Assert(evenNumberIsB is TypeB);
            Debug.Assert(evenNumberIsB.Dependency is ISpecializedDependencyForB);

            var oddNumberIsC = repository.GetById(101);
            Debug.Assert(oddNumberIsC is TypeC);
            Debug.Assert(oddNumberIsC.Dependency is ISpecializedDependencyForC);

        }
    }
}
StuartLC
  • 104,537
  • 17
  • 209
  • 285
  • Thank you very much for your time and this comprehensive explanation. I finally came up with an other solution to this problem. The idea is in essence similar to what you and Erwan suggest, but I achieve the DI differently. I'll post it ASAP ! – tobiak777 Mar 25 '15 at 10:08
1

Could whatever it is that knows about the dependencies live behind an interface IDependencyProvider which has a function

IDependency GetDependency(Type type).  

This could even just return an object and the class that realises the interface needs to know all the sub types and their associated dependencies.

AbstractMethod is then changed to:

void AbstractMethod(IDependencyProvider provider);

In your sub classes you then override this and call

var dependency = provider.GetDependency(this.GetType());

Your middle tier then knows nothing about the sub types or the sub dependencies.

Tim Rutter
  • 4,549
  • 3
  • 23
  • 47
0

It's an interesting problem, what I was thinking is that your repository knows about and creates the TypeB and TypeC classes and so you can add the correct dependency at that point

public class TypeARepository
{
    private ISpecializedDependencyForB depB;
    private ISpecializedDependencyForC depC;
    public TypeARepository(ISpecializedDependencyForB depB, ISpecializedDependencyForC depC)
    {
        this.depB = depB;
        this.depC = depC;
    }

    public TypeA GetById(string id)
    {
        if (id == "B")
        {
            return new TypeB(depB);
        }
        else
        {
            return new TypeC(depC);
        }

    }
}

The TypeB and TypeC would then implement their abstract methods with their private ref to the dependency rather than having it passed in in the method.

I come across this problem in various forms myself from time to time and it always seems to me that if there is that hard link between the types just having it setup via an injection config or the like is wrong. As it allows the installer to potentially set a bad config

This approach also allows you to inject your dependencies with unity

Ewan
  • 1,261
  • 1
  • 14
  • 25
  • nb. I do agree with @Steven's comment about not injecting into entity type objects generally. But in this case with a hard link between the types, I can't see a good way to invert and have the dependencies as services – Ewan Mar 24 '15 at 15:36
-1

Thank you a lot for your interest in my question, I came up with a solution yesterday evening. The objective is to keep things transparent for the client and to take full advantage of polymorphism by syntaxes such as baseObjectReference.AbstractMethodCall().

I finally realized that I was able to achieve what I'm after by taking advantage of the static modifier and using it for DI purposes. So I have that :

public abstract class TypeA 
{ 
    public abstract void AbtractMethod();
}

public class TypeB : TypeA
{
    private ISpecializedDependencyForB SpecializedDependencyForB 
     { 
          get 
          { 
               return GetSpecializedDependencyForB.CreateSpecializedDependencyForB(); 
          } 
    }
    public override void AbtractMethod() { // do stuff with dependency }
}


public static class GetSpecializedDependencyForB
{
    public static ISpecializedDependencyForB DependencyForB
    {
        return CreateSpecializedDependencyForB();
    }
    public delegate ISpecializedDependencyForB CreateSpecializedDependencyForBDelegate();
    public static CreateSpecializedDependencyForBDelegate CreateSpecializedDependencyForB;
}

And then, in my unity container I add this code :

public static void RegisterTypes(IUnityContainer container)
        {
            // .... registrations are here as usual 
            GetSpecializedDependencyForB.CreateSpecializedDependencyForB = CreateMyDomainService;
        }

Having this method in the same unity config class :

private ISpecializedDependencyForB CreateMyDomainService()
    {
        return container.Value.Resolve<ISpecializedDependencyForB>();
    }

And finally, I can simply use my object like this :

TypeA myDomainObject = database.TypeARepository.GetById(id); 
myDomainObject.AbtractMethod();

And that's it !

So four things here :

  • The first one is that I inject the delegate that will create and instance of the service.
  • Then it is thread safe because static member is only written one time at the beginning of the application. All other accesses will be read. Moreover two threads won't share the same instance of the dependency since the delegate creates a new one all the time.
  • Also one interesting thing is that I can rely on my existing unity container configuration, no extra code is needed. It is important because my dependency may need other dependency to be constructed.
  • And finally the unity container is anyway also static, so there is no memory leak.

It's basically a manual and easy to set up "DI framework" sitting beside Unity.

And more importantly it works like a charm ! I'm finally satisfied with my design. I will only use this approach for polymorphic situations since injecting the right dependency in the method is easy for other situations. However it might be interesting to fully encapsulate the domain model using this approach.

tobiak777
  • 3,175
  • 1
  • 32
  • 44