We have implemented the user registration function and now want to increase the logging function. In particular, before and after the user registration, output a log respectively. We can of course modify the original business code.
Now ask two questions from another angle:
1. Team development, we are likely to not get the source code, how to increase this function.
2. This demand is to increase the log, and then add other requirements (such as exception handling), is still to change the business class it.
To sum up:
We want to do the enhancements of the class without modifying the original business code. Our design should conform to the object-oriented principle: open to expansion, closed to modification .
There are ways to do that. We try the following methods: use the adorner pattern to do the enhanced use of the class . NET proxy mode to do class enhancements use Castle to do class enhancements use Unity to do class enhancements (continued) use AUTOFAC to do class enhancements Original Business Class
Business model
Namespace Testaopbydecorator
{public
class User
{public
string Name {get; set;}
public int Id {get; set;}}}
Interface design
Namespace Testaopbydecorator
{public
interface iuserprocessor
{
void RegisterUser (user user);
}
}
Business implementation
Using System;
Namespace Testaopbydecorator
{public
class Userprocessor:iuserprocessor
{public
void RegisterUser (User user)
{
if (user = null)
{return
;
}
Console.WriteLine (String. Format ("registered with a user {0}:{1}", user.) Id, user. Name);}
}
Upper Call
Using System;
Namespace Testaopbydecorator
{
class program
{
private static user user = new User {Id = 1, Name = "Yunnan Red "};
static void Main (string[] args)
{
Register ();
Console.readkey ();
}
private static void Register ()
{
Iuserprocessor processor = new Userprocessor ();
Processor. RegisterUser (user);}}
use Unity to do class enhancement
We will use the unity of the third party to do business enhancements to the existing classes, first using the NuGet installation.
Business Enhancements Implementation
Using System;
Using System.Collections.Generic;
Using Microsoft.Practices.Unity;
Using Microsoft.Practices.Unity.InterceptionExtension; Namespace Testaopbyunitybehavior {public class Userprocessorlogbehavior:iinterceptionbehavior {public
BOOL WillExecute {get {true;
} public ienumerable<type> Getrequiredinterfaces () {return type.emptytypes;
Public Imethodreturn Invoke (imethodinvocation input, getnextinterceptionbehaviordelegate getNext) {User user = input.
Inputs[0] as User;
Before (user);
Invokeinterceptionbehaviordelegate Delegatemethod = GetNext ();
Imethodreturn Returnmessag = Delegatemethod (input, getNext);
After (user);
return RETURNMESSAG; } private void after (user user) {Console.WriteLine ("Log End:" + user.)
Name); } private void before (user user) {Console.WriteLine ("Log Start:" + user.)
Name);
}
}
}
Upper Call
Using Microsoft.Practices.Unity;
Using Microsoft.Practices.Unity.InterceptionExtension;
Using System; Namespace Testaopbyunitybehavior {class Program {private static user user = new User {Id = 1, Name = "a"
DMin "};
static void Main (string[] args) {registerandlog ();
Console.readkey (); private static void Registerandlog () {//create container Iunitycontainer container = new U
Nitycontainer (); Register extension container.
Addnewextension<interception> (); Container. Registertype<iuserprocessor, userprocessor> (New Injectionconstructor (),//builder intercept New Interceptor<interfaceinterceptor> (),//Register interceptor New Interceptionbehavior<userprocessorlogbehavior>
;()//Registration behavior interception);
User User = new User {Id = 1, Name = "Li Dandan"}; Get the service from the container (assuming that the interceptor is added, the dynamic object is generated here) iuserprocessor processor = container.
Resolve<iuserprocessor> (); Processor.
RegisterUser (user);
}
}
}
Compare the business presentation before and after the expansion
Here we use the code to configure the Interceptor (AOP Dependency Injection) to the original business class, and to use the configuration file in a way that is more flexible.
Configuration file: Unity.config
<?xml version= "1.0" encoding= "Utf-8"?> <configuration> <configSections> <section name= "Unity" Type= "Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, MICROSOFT.PR Actices. Unity.configuration "/> </configSections> <unity xmlns=" http://schemas.microsoft.com/practices/2010/ Unity "> <alias alias=" singleton "type=" Microsoft.Practices.Unity.ContainerControlledLifetimeManager, Microsoft.Practices.Unity "/> <sectionextension type=" Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration "/> <container> <extension type=" Intercep tion "/> <register type=" Iinterceptionbehavior "mapto=" Testaopbyunityconfig.userprocessorlog Behavior,testaopbyunityconfig "name=" Userprocessorlogbehavior "> </register&Gt <register type= "Testaopbyunityconfig.iuserprocessor,testaopbyunityconfig" mapto= "TestAopByUnityConfig". Userprocessor,testaopbyunityconfig "> <interceptionbehavior name=" Userprocessorlogbehavior "/> < Interceptor type= "Interfaceinterceptor"/> </register> </container> </unity> </configur
Ation>
Upper Call
Using Microsoft.Practices.Unity;
Using Microsoft.Practices.Unity.Configuration;
Using Microsoft.Practices.Unity.InterceptionExtension;
Using Microsoft.Practices.Unity.InterceptionExtension.Configuration;
Using System;
Using System.Configuration; Namespace Testaopbyunityconfig {class Program {private static user user = new User {Id = 1, Name = ' adm
In "};
static void Main (string[] args) {registerandlog ();
Console.readkey (); private static void Registerandlog () {var map = new Execonfigurationfilemap {Execonfigfil ename = "Unity.config"};//Use this profile var config = configurationmanager.openmappedexeconfiguration (map, Configu
Rationuserlevel.none); var section = (unityconfigurationsection) config.
GetSection ("Unity"); Read config file node var container = new UnityContainer (); Container.
Loadconfiguration (section);
Get the service from the container (because the interceptor is added, the dynamic object is generated here) Iuserprocessor processor = container.
Resolve<iuserprocessor> (); Processor.
RegisterUser (user);
}
}
}