0

I am using C# 4.7.2 and PRISM 6 with Unity.

Now, in a loop an instance of SomeClass is needed. Foreach loop run I need a new instance of SomeClass. The common implementation would look like the code in MyMethod_CommonImplementation.

How do implement that code in the DI pattern correctly (in MyMethod)? Of course, I could inject the UnityContainer and use container.Resolve. But I believe that would be service providing, not dependency injection.

The example shows a loop doing five runs. So I could inject five instances of SomeClass. But is that really the correct way of doing this?

Registering works fine, by the way, _exampleName is set up correctly.

public class MyClass
{

    IMyInterface _exampleName;


    public MyClass(IMyInterface exampleName)
    {
        _exampleName = exampleName;
    }


    private void MyMethod()
    {
        for ( int index = 0 ; index < 5 ; index++ )
        {
            // at this place  I want to "reset" the instance of _exampleName for each index
            _exampleName.PropertyName = index
            _exampleName.DoSomeImportantWork();
        }
    }


    private void MyMethod_CommonImplementation()
    {
        for ( int index = 0 ; index < 5 ; index++ )
        {
            SomeClass exampleClassName = new SomeClass();           
            exampleClassName.PropertyName = index
            exampleClassName.DoSomeImportantWork();
        }
    }

}
1
  • You can inject a factory that can build what you need Commented Oct 14, 2018 at 8:30

2 Answers 2

0

First of all, thank you so much for your answer and all the work for that.

First things first, the example

private void MyMethod_CommonImplementation()
{
    for ( int index = 0 ; index < 5 ; index++ )
    {
        SomeClass exampleClassName = new SomeClass();           
        exampleClassName.PropertyName = index
        exampleClassName.DoSomeImportantWork();
    }
}

isn't part of the real code, I used it to clarify what I need.

In the real code SomeClass derives from serveral interfaces which segregate the functionality of SomeClass into pieces that belong together.

Independently of any DI the implementation would look like this

private void MyMethod_CommonImplementation()
{
    for ( int index = 0 ; index < 5 ; index++ )
    {
        ISomeFunctionality exampleFunc = new SomeClass();           
        exampleFunc.PropertyName = index
        exampleFunc.DoSomeImportantWork();
    }
}

Indeed, one could still argue, that's still temporal coupling. But for reasons of stability and maintainability I prefer this kind of implematation over overloading a method. DoSomeImportantWork() however validates the given data.

After your answer I was implementing the factory pattern. So my implementation looks like this, now

public interface IFactory<T>
{
    T CreateInstance();
}    


public interface ISomeClass
{
    int PropertyName { get; set; }

    void DoSomeImportantWork(); 
}


internal SomeClass : ISomeClass, IFactory<ISomeClass>
{

    public int PropertyName { get; set; }

    public void DoSomeImportantWork()
    {
        // ...
    }

    public ISomeClass CreateInstance()
    {
        return new SomeClass();
    }
}

public class MyClass
{

    IFactory<ISomeClass> _exampleFactory;


    public MyClass(IFactory<ISomeClass> exampleFactory)
    {
        _exampleFactory = exampleFactory;
        MyMethod();
    }


    private void MyMethod()
    {
        for ( int index = 0 ; index < 5 ; index++ )
        {
            ISomeClass exampleName = _exampleFactory.CreateInstance();
            exampleName.PropertyName = index;
            exampleName.DoSomeImportantWork();
        }
    }
}

I chose the factory pattern over the proxy pattern, because if I got it right I would have to implement the proxy in a third class.

Still, I am wondering, if that's a correct way of doing this.

Sign up to request clarification or add additional context in comments.

Comments

0

Your code is subject to several design smells. Let's dissect your code.

In your code you do the following:

_exampleName.PropertyName = index;
_exampleName.DoSomeImportantWork();

This code exhibits the Temporal Coupling design smell. Even though PropertyName must be set before calling DoSomeImportantWork, on a structural level this API gives us no indication of temporal coupling.

Besides this, by changing the state of the IMyInterface, it makes the IMyInterface stateful. Services injected through DI, however, should be stateless from perspective of their consumers. Or as stated by Dependency Injection Principles, Practices, and Patterns:

Conceptually, there's only one instance of a service Abstraction. During the lifetime of a consumer, it shouldn't be concerned with the possibility that multiple instances of a Dependency can exist. Otherwise, this causes needless complication to the consumers, which means the Abstraction isn't designed to their benefit. [section 6.2]

So to fix this, it's better to pass that runtime value through the method of the abstraction, as follows:

_exampleName.DoSomeImportantWork(index);

This removes the Temporal Coupling, and removes the need for the consumer to know there might be multiple instances involved, and might even remove the need to have multiple instances at all.

But in case still multiple, short-lived instances must be created, you can hide their existence behind a Proxy:

public class MyInterfaceProxy : IMyInterface 
{
    public void DoSomeImportantWork(int index)
    {
        var instance = new MyInterfaceImpl();
        instance.DoSomeImportantWork(index);
    }
}

Instead of injecting MyInterfaceImpl directly into MyClass, you can now inject MyInterfaceProxy.

Do note however, that there are many ways to define such proxy. If you make MyInterfaceProxy part of the Composition Root, you could even safely inject the Container into the Proxy. This would not lead to the Service Locator anti-pattern, because a Service Locator is only something that can exist outside the Composition Root. Another thing that is happening in your code is the following:

SomeClass exampleClassName = new SomeClass();           
exampleClassName.PropertyName = index
exampleClassName.DoSomeImportantWork();

Depending on the function and implementation of SomeClass, the code might be exhibiting the Control Freak anti-pattern (which is a DI-specific way of saying you are violating the Dependency Inversion Principle). This is the case when SomeClass contains some undeterministic behavior, or contains behavior that you want to mock, replace, or intercept at a later point in time. In that case we call SomeClass a Volatile Dependency (see section 1.3.2, of the book). Volatile Dependencies should be hidden behind an abstraction and injected through constructor injection.

Whether or not SomeClass actually is a Volatile Dependency is impossible to answer, based on the information given in the question. But when it is, it deserves a code structure similar to that of IMyInterface.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.