Application of Attribute in .NET Programming (5)
Application of Attribute on Interception Mechanism
From this section, we discussed the advanced application of Attribute, and I have prepared an actual example: We have an order processing system, when a order is submitted, the system checks inventory, if the stock deposit satisfies the number of orders, the system Record the order processing record, then update the stock, if the stock stock is lower than the number of orders, the system makes the corresponding record while sending an email to the inventist. For the convenience of demonstration, we have simplified the example:
//INVENTORY.CS
Using system;
Using system.collections;
Namespace NiwalkerDemo
{
Public Class Inventory
{
Private hashtable inventory = new hashtable ();
Public inventory ()
{
Inventory ["ITEM1"] = 100;
Inventory ["Item2"] = 200;
}
Public Bool Checkout (String Product, Int Quantity)
{
INT Qty = getquantity (product);
Return Qty> = quantity;
}
Public int getQuantity (String Product)
{
INT Qty = 0;
IF (Inventory! = NULL)
Qty = (int) inventory;
Return QTY;
}
Public void update (String Product, Int Quantity)
{
INT Qty = getquantity (product);
Inventory [Product] = Qty-Quantity;
}
}
}
//Logbook.cs
Using system;
Namespace NiwalkerDemo
{
Public Class logbook
{
Public Static void log (String logdata)
{
Console.writeline ("log: {0}", logdata);
}
}
}
//Order.cs
Using system;
Namespace NiwalkerDemo
{
Public Class Order
{
Private int orderId;
PRIVATE STRING PRODUCT;
Private int quantity;
Public ORDER (int Order)
{
THIS.Orderid = OrderId;
}
Public void submit ()
{
Inventory Inventory = new inventory (); // Create a stock object
// Check inventory
IF (Inventory.Checkout (Product, Quantity))
{
Logbook.log ("Order" ORDERID "Available");
Inventory.Update (Product, Quantity);
}
Else
{
Logbook.log ("ORDER" Orderid "Unavailable");
Sendemail ();
}
}
Public String ProductName
{
Get {returnophus
Set {product = value;}}
Public int OrderID
{
Get {return ORDERID;
}
Public Int Quantity
{
Get {return quantity;
Set {Quantity = Value;}
}
Public void sendemail ()
{
Console.WriteLine ("Send Email to Manager);
}
}
}
Here is the calling program:
//Appmain.cs
Using system;
Namespace NiwalkerDemo
{
Public Class Appmain
{
Static void main ()
{
Order Order1 = New ORDER (100);
ORDER1.PRODUCTNAME = "Item1";
ORDER1.quantity = 150;
Order1.submit ();
Order Order2 = New Order (101);
ORDER2.PRODUCTNAME = "Item2";
ORDER2.quantity = 150;
Order2.submit ();
}
}
}
The program seems yet, and the business object encapsulates business rules, and the results of operation also meet the requirements. But I seem to hear you complaining, no? When your customer's needs changes (customers always change their needs), such as inventory check rules are not a single check product, but also check if the product is booked, then you need to change Inventory. The code, but also modify the code in Order, our example is just a simple business logic, and the actual situation is more complicated than this. The problem is that the ORDER object is tight between the other objects, from OOP's point of view, such a design is problematic, if you write this program, at least you will not be passed in my team.
You said: "No problem! We can draw business logic to a specially designed object to handle transactions." Well, good idea, if you think so, maybe I can also give you a proposal Using Observer Design Pattern (Observer Design Mode): You can use Delegate, define a beforSubmit and an afterSubmit event in the ORDER object, and then create an object chain list, insert the relevant object into this list, so you can implement Order The interception of the submit event is automatically handled before the ORDER submits and submits. If you are interested, you can do your own code yourself, perhaps considering how to handle your interaction between objects in a distributed environment (ORDER and Inventory).
Fortunately, the .NET Framework provides support for this technology. In the object Remoting and Components in .NET Framework, there is an important intercepting mechanism. In object transotiet, the interaction between the objects between different applications requires crossing their domain boundaries, each application domain can be subdivided. For multiple context, each application field has at least one default Context, even in the same application domain, there is also a problem that crossing different contexts. NET's component service develops COM component services, which uses Context Attribute to implement the same interception of COM . By interception of calling objects, we can perform pre-processing and post-processing on a method of call, and also solve the above problems. Need to remind you if you can check CONTEXTATTRIBUTE in the MSDN document, I can guarantee any information that helps to understand the ContextAttribute, you will see this: "This Type supports the .NET Framework Infrastructure and is not Intended to Be Used Directly from Your Code. "-" This type supports the .NET Framework infrastructure, it is not intended to be used directly for your code. "However, in the MSDN site, you can see some information about this ( See the reference link behind the article).
Let's introduce several classes and some concepts, first of all:
ContextAttribute class
ContextAttribute is derived from Attribute, and it also implements the icontextAttribute and IconTextProperty interface. All custom ContextAttributes must be derived from this class. Constructor: ContextAttribute: The constructor has a parameter to set the name of ContextAttribute.
Public property: Name: Read-only properties. Returns the name of ContextAttribute
Public method: getPropertiesforneWContext: Virtual method. Add an attribute collection to the new Context. ISCONTEXTOK: Virtual Method. Query if there is a specified property in customer context. IsnewContextok: virtual method. Returns True by default. An object may exist multiple contexts, using this method to check if there is a conflict in the new context. Freeze: Virtual method. This method is used to locate the last position of the CONTEXT created.
ContextBoundObject class
Implementing the intercepted class, you need to derive from the ContextBoundObject class, this class object is specified by Attribute, which can be intercepted by the CONTEXT. This class is derived from MarshalByrefObject.
The following is the interface involved:
IMessage: Defines the implementation of messages transmitted. A message must implement this interface.
IMESSAGESINK: Defines the interface of the message receiver, and a message receiver must implement this interface.
There are also several interfaces, we will introduce in the principles of the next section of the intercepting architecture. (to be continued)
Reference article: decouple components by incjecting Custom Services INTO YOUR Object's Interception CHAIN