This article is a companion article titled "How to Use AOP to simplify model and viewmodel design in mvvm. Please read the previous article before reading this article. Otherwise, you may not have a deep understanding of the problem.
As mentioned in the previous article, we can use the AOP method. Specifically, we use a third-party framework (postsharp) to implementCodeInjection. The postsharp method is Static injection, which requires changing the Il code.
Please refer to the following. The IL code in the customer type has actually been changed. Postsharp changes the compilation behavior of Visual Studio.
Is there any other method besides this? Actually, I will introduce you to another PRACTICE IN THIS ARTICLE: Use the Interception Function (interception function provided by unity) in the Enterprise Library officially provided by Microsoft)
For introduction and download of Enterprise Library, visit the following address:
Http://entlib.codeplex.com/
This example is based on Enterprise Library 5.0.
Let's take a look at the example below. Suppose we have another model type called order, which indicates order. We hope that its code will be as concise as below.
using system; namespace wpfmvvmsample. models { Public class order: modelbase { Public int orderid {Get; set ;} Public datetime orderdate {Get; Set ;}}
[Note] Here we only inherit modelbase, and there is nothing special.
Please rest assured that we can do it. You only need to continue reading.
1. Add reference
We need to referenceProgramSet
2. Compile an interceptionbehavior
Behavior is an action we need to inject. This is a specialized term in interception.
[Note] This articleArticleFor more information about policy injection, see the instructions in Enterprise Library.
Using System. LINQ; Using Microsoft. Practices. Unity. interceptionextension; Namespace Wpfmvvmsample { Public Class Policypropertychangedbahavior: iinterceptionbehavior { Public System. Collections. Generic. ienumerable <system. type> getrequiredinterfaces (){ Return Enumerable. Empty <system. type> ();} Public Imethodreturn invoke (imethodinvocation input, getnextinterceptionbehaviordelegate getnext) {var result = getnext () (input, getnext ); // First execute the Method VaR methodname = input. methodbase. Name; var type = input. Target. GetType (); var targetmethod = type. getmethod ( "Onpropertychanged" , System. reflection. bindingflags. nonpublic | system. reflection. bindingflags. instance ); If (Methodname. startswith ( "Set _" ) & Targetmethod! = Null ) // Only inject this method. {Var propertyname = methodname. substring (4 ); // Parse the property name Targetmethod. Invoke (input. Target, New [] {Propertyname }); // Execute this method } Return Result ;} Public Bool Willexecute {get { Return True ;}}}}
[Note] the above code is very similar to the previous postsharp method, isn't it?
3. Modify the modelbase type
By default, Unity provides intercept and supports two main interceptors: transparentproxyinterceptor and virtualmethodinterceptor. We are going to use the first one here. It has a simple requirement, that is, the type to intercept, inheritanceMarshalbyrefobject
The code is modified as follows:
Using System; Using System. componentmodel; Using System. diagnostics; Namespace Wpfmvvmsample. Models { Public Abstract Class Modelbase: Marshalbyrefobject , Inotifypropertychanged { Public Event Propertychangedeventhandler propertychanged; Protected Void Onpropertychanged ( String Name ){If (Propertychanged! = Null ) Propertychanged ( This , New Propertychangedeventargs (name )); // To facilitate debugging, We output a line of information in the output window. Debug. writeline ( String . Format ( "{0} changed" , Name ));}}}
4. write code to implement interception and injection
Using System; Using System. windows; Using Microsoft. Practices. Unity. interceptionextension; Namespace Wpfmvvmsample {/// <Summary> /// Interaction logic for mainwindow. XAML /// </Summary> Public Partial Class Mainwindow: window { Public Mainwindow () {initializecomponent (); loaded + = New Routedeventhandler (mainwindow_loaded );} Void Mainwindow_loaded ( Object Sender, routedeventargs e) {var order = intercept. throughproxy ( New Models. Order (), New Transparentproxyinterceptor (), New [] { New Notifypropertychangedbahavior ()}); Order. orderdate = datetime. Now; order. orderid = 5 ;}}}
Please note that the Order instance cannot be created directly using the new method, but must be created using intercept.
Press F5 for debugging. We can also see the relevant message output in the output window. This indicates that the custom behavior is working, because it is the onpropertychanged method in the base class.
It is worth mentioning that, unlike postsharp, the interception we use here is dynamic interception and it will not modify our code. Please refer to the order code, which is the same as that in Visual Studio.