📜 ⬆️ ⬇️

Unity First Steps: DI / IoC & AOP

Introduction


If you have ever heard such words as IoC, DI, AoP, but do not have a clear understanding of these terms, I hope this article will help you to go bust using the example of working with a Microsoft Unity container.

So let's get down to the theory:

Inversion of Control (IoC) and Dependency Injection (DI)


For the definition of IoC, we turn to Wikipedia :

Inversion of Control * (IoC) is an important principle of object-oriented programming that is used to reduce connectivity in computer programs.
')
IoC is also known as Dependency Injection Principle. Dependency Injection is used in almost all frameworks. It is used by programmers using object-oriented programming languages ​​such as Smalltalk, C ++, Java, or .NET languages.


* Immediately I wanted to make a reservation that I prefer not to use the Russian-language translation for IoC, but still if I am forced to do this, I will use it as a "control inversion"

For the definition of DI also turn to Wikipedia :

Dependency injection (eng. Dependency injection) refers to the process of providing external dependency to a software component and is a specific form of “inversion of control”, where changing the order of communication is the way to obtain the required dependency.


The classic example for determining how tightly your objects are linked to each other is to try to copy a class from your subject area to a new application and try to run it, if that doesn't work, then copy the related classes. Usually, as a result of these manipulations, your old application is almost entirely copied into the new one.

To resolve problems of dependencies of one object from another, usually an object that has a dependency is responsible for creating / obtaining the object it needs (I would like to draw your attention to patterns such as Factory, Registry ).

There are a great many examples of implementation with IoC and DI casting a pseudo-code. Therefore, I don’t really want the article to grow because of them, and I can hardly provide you with a better understanding than with practical use.

I think it will be useful to list the .NET DI / IoC containers here :



Aspect-oriented programming (AoP)



I admit I am a meticulous admirer of Wikipedia :

Aspect-oriented programming (AOP) is a programming paradigm based on the idea of ​​separating functionality, especially cross-cutting functionality, to improve program partitioning into modules.


I would like to add that Aspect-oriented programming (AOP) is also intended to come to the aid of the PLO in order to reduce the amount of code written in applications.

Most often, the use of AOP is reduced to the implementation of everyday routine tasks such as logging, caching, validation, and access control. You can argue and say that you can solve this problem by enveloping your business objects of the Decorator template ( rus. ), But the fact is that this necessitates changing the consumer code, and AOP allows you to do this easily and naturally.

Famous frameworks:



About Microsoft Enterprise Library


As you know, in October 2008, Microsoft updated the version of the Enterprise Library to 4.1 , respectively, one of its components of the Unity Application Block to version 1.2 . The Microsoft Enterprise Library is developed by the patterns & practices group. The Microsoft Enterprise Library is a set of functional blocks designed to help developers do their usual routine tasks. Functional blocks - something like a manual, the source code provided in them can be used "as is", can be expanded or modified by developers according to their needs. Microsoft Enterprise Library consists of the following blocks:



About Unity Application Block



a lightweight, extensible, injection-dependent container with support for adding dependencies to the constructor, the property and the method call, in the same way as the implementation of interception through extensions. You can use it with the Enterprise Library (EntLib) to generate objects, both your own and the Enterprise Library. However, the Unity Application Block differs from the rest of the EntLib function blocks at several key points:



Long-awaited In Action



Requirements



For the example below, we’ll need:

  1. Installed .NET Framework 3.5 SP1
  2. Your favorite IDE (Notepad .. Visual Studio 2008 SP1 )
  3. Installed Unity
  4. 15-20 min time and some interest


Process



First, create a ConsoleApplication called UnityInAction1.

Next, add links to the following assembly:



Create an ILogger interface in our application:

namespace UnityInAction1 { interface ILogger { void Write( string msg); } }
* This source code was highlighted with Source Code Highlighter .
  1. namespace UnityInAction1 { interface ILogger { void Write( string msg); } }
    * This source code was highlighted with Source Code Highlighter .
  2. namespace UnityInAction1 { interface ILogger { void Write( string msg); } }
    * This source code was highlighted with Source Code Highlighter .
  3. namespace UnityInAction1 { interface ILogger { void Write( string msg); } }
    * This source code was highlighted with Source Code Highlighter .
  4. namespace UnityInAction1 { interface ILogger { void Write( string msg); } }
    * This source code was highlighted with Source Code Highlighter .
  5. namespace UnityInAction1 { interface ILogger { void Write( string msg); } }
    * This source code was highlighted with Source Code Highlighter .
  6. namespace UnityInAction1 { interface ILogger { void Write( string msg); } }
    * This source code was highlighted with Source Code Highlighter .
  7. namespace UnityInAction1 { interface ILogger { void Write( string msg); } }
    * This source code was highlighted with Source Code Highlighter .
namespace UnityInAction1 { interface ILogger { void Write( string msg); } }
* This source code was highlighted with Source Code Highlighter .


Next we implement it in the Logger class:

  1. using System;
  2. namespace UnityInAction1
  3. {
  4. class Logger: ILogger
  5. {
  6. #region ILogger Members
  7. public void Write ( string msg)
  8. {
  9. Console .WriteLine ();
  10. Console .WriteLine ( "*** In logger ***" );
  11. Console .WriteLine ( String .Format ( "message {0}" , msg));
  12. }
  13. #endregion
  14. }
  15. }

* This source code was highlighted with Source Code Highlighter .


So our usual application would look:

  1. using System;
  2. namespace UnityInAction1
  3. {
  4. class program
  5. {
  6. static void Main ( string [] args)
  7. {
  8. ILogger logger = new Logger ();
  9. logger.Write ( "My message" );
  10. Console .ReadKey ();
  11. }
  12. }
  13. }

* This source code was highlighted with Source Code Highlighter .


However, from the point of view of the IoC / DI approach, this does not quite suit us, so we want to place our Logger in a container (for example, in order to replace [and it will only be necessary to replace the container configuration site, and not the entire coverage code, as it usually happens] on the stub when testing):

  1. using System;
  2. using Microsoft.Practices.Unity;
  3. namespace UnityInAction1
  4. {
  5. class program
  6. {
  7. static void Main ( string [] args)
  8. {
  9. IUnityContainer container = new UnityContainer ();
  10. container.RegisterType <ILogger, Logger> ( new ContainerControlledLifetimeManager ());
  11. var logger = container.Resolve <ILogger> ();
  12. logger.Write ( "My message" );
  13. Console .ReadKey ();
  14. }
  15. }
  16. }

* This source code was highlighted with Source Code Highlighter .


Well, I think this example is quite enough to start.

Now we add the requirement for measuring the execution time of the ILogger.Write () method for all implementations of this interface, it is clear that with the help of the OOP, the implementation of this condition becomes more difficult, therefore we will look at this example from the point of view of AOP. First, let's override the description of ILogger by introducing a new .NET attribute :

  1. namespace UnityInAction1
  2. {
  3. interface ILogger
  4. {
  5. [Stopwatch]
  6. void Write ( string msg);
  7. }
  8. }

* This source code was highlighted with Source Code Highlighter .


Description of the Stopwatch attribute:

  1. using System;
  2. using Microsoft.Practices.Unity.InterceptionExtension;
  3. namespace UnityInAction1
  4. {
  5. class Stopwatch: HandlerAttribute
  6. {
  7. public override ICallHandler CreateHandler (Microsoft.Practices.Unity.IUnityContainer container)
  8. {
  9. return new StopwatchCallHandler ();
  10. }
  11. }
  12. public class StopwatchCallHandler: ICallHandler
  13. {
  14. public int Order { get ; set ;}
  15. public StopwatchCallHandler (): this (0) {}
  16. public StopwatchCallHandler ( int order)
  17. {
  18. Order = order;
  19. }
  20. #region ICallHandler Members
  21. public IMethodReturn Invoke (IMethodInvocation input, GetNextHandlerDelegate getNext)
  22. {
  23. System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch ();
  24. sw.Start ();
  25. var result = getNext (). Invoke (input, getNext);
  26. sw.Stop ();
  27. Console .WriteLine ();
  28. Console .WriteLine ( String .Format ( " Elapsed time {0} ms" , sw.ElapsedMilliseconds));
  29. return result;
  30. }
  31. #endregion
  32. }
  33. }

* This source code was highlighted with Source Code Highlighter .


Well, add an extension for our container:

  1. using System;
  2. using Microsoft.Practices.Unity;
  3. using Microsoft.Practices.Unity.InterceptionExtension;
  4. namespace UnityInAction1
  5. {
  6. class program
  7. {
  8. static void Main ( string [] args)
  9. {
  10. IUnityContainer container = new UnityContainer ();
  11. container.RegisterType <ILogger, Logger> ( new ContainerControlledLifetimeManager ());
  12. container.AddNewExtension <Interception> ();
  13. container.Configure <Interception> ()
  14. .SetInterceptorFor <ILogger> ( new TransparentProxyInterceptor ());
  15. var logger = container.Resolve <ILogger> ();
  16. logger.Write ( "My message" );
  17. Console .ReadKey ();
  18. }
  19. }
  20. }

* This source code was highlighted with Source Code Highlighter .


Now every implementation of ILogger.Write () will output measurements of the execution time of this method, isn't that great?

Materials





In conclusion



I hope this article gives a good start to your research in the field of quality code.

PS This is my first post on Habré, so a little about myself : the horizon of my interests is very wide, in its technical component it is .NET development (ASP.NET, Sharepoint, WWF, Silverlight), development techniques (Agile, Scrum, XP), engineering techniques (TDD, DDD, MDA, AOP).

Source: https://habr.com/ru/post/50845/


All Articles