Шрифт:
StreamWriter logFile = null;
while (logFile == null) {
logFile = File.AppendText(_logFileName);
}
logFile.WriteLine(msg);
logFile.Close;
}
}
internal class MyCallTraceServerContextSink: IMessageSink {
internal IMessageSink _nextSink;
internal MyCallTraceAttribute _property;
internal IMessage _replyMsg;
internal MyCallTraceServerContextSink {
MyCaiiTraceAttribute property, IMessageSink nextSink) {
_property = property;
_nextSink = nextSink;
_replyMsg = null;
{
public virtual IMessage SyncProcessMessage(IMessage reqMsg) {
if (reqMsg is IMethodMessage) {
IMethodMessage call = reqMsg as IMethodMessage;
lock(_property){
_property.LogMessage("===" + call.TypeName);
_property.LogMessage("\n" + call.MethodName +
" \n\t <<<IN>>> parameters: (");
for (int i = 0; i < call.ArgCount; i++) {
if (i > 0) _property.LogMessage(", ");
_property.LogMessage(call.GetArgName(i) +
"= " + call.GetArg(i));
}
_property.LogMes sage(")\n");
}
}
_replyMsg = _nextSink.SyncProcessMessage(reqMsg);
if (_replyMsg is IMethodReturnMessage) {
IMethodReturnMessage retMsg =
(IMethodReturnMessage) _replyMsg;
Exception e = retMsg.Exception;
if (e!= null) {
Console.WriteLine(e.Mes sage);
return _replyMsg;
}
lock(_property) {
_property.LogMessage("===" + retMsg.TypeName);
_property.LogMessage("\n" + retMsg.MethodName +
" \n\t <<<OUT»> parameters: (");
for (int i = 0; i < retMsg.OutArgCount; i++) {
if (i > 0) _property.LogMessage(", ");
_property.LogMessage(retMsg.GetOutArgName(i) +
" = " + retMsg.GetOutArg(i));
}
_property.LogMes sage(")\n");
}
}
return _replyMsg;
public virtual IMessageCtrl AsyncProcessMessage(IMessage msg,
IMessageSink replySink) {
throw new InvalidOperationExcept;
}
public IMessageSink NextSink {
get {
return _nextSink;
}
}
}
}
Комментарии к коду:
1. Данный код содержит определения двух классов:
? MyCallTraceAttribute
Этот публичный класс доступен всем приложениям, имеющим доступ к сборке MyServer.ехе
? MyCallTraceServerContextSink
Этот класс является внутренним (internal) для сборки MyServer.ехе и не доступен за ее пределами.
2. Классу MyCallTraceAttribute приписан атрибут [AttributeUsage (AttributeTargets. Class)]. Данный атрибут используется при определении пользовательских атрибутов для задания элементов, которым может быть приписан данный атрибут. В данном случае атрибут MyCallTraceAttribute можно приписать только классу (но нельзя приписать, например, какому-то методу).
3. Комментарии к коду класса MyCallTraceAttribute:
? Класс MyCallTraceAttribute является производным классом от класса ContextAttribute и реализует интерфейс IContributeServerContextSink. В свою очередь класс ContextAttribute реализует интерфейсы IContextProperty и IContextAttribute.
Реализация интерфейсов IContextProperty и IContextAttribute обеспечивает выбор контекста для размещения активируемого объекта (в старом или в новом контексте), а в случае формирования нового контекста — назначение ему свойств, которые объект может вызывать в своем коде явно.
Реализация интерфейса IContributeServerContextSink позволяет включить в конец цепочки перехватчиков, которые перехватывают все входящие в контекст вызовы, новый перехватчик. Это позволяет декларативно связать некоторый класс с некоторым автоматическим сервисом, что и является реализацией идей аспектно-ориентированного программирования.
? Константа PROPERTY_NAME будет использована для задания имени свойству контекста. Каждое свойство контекста имеет имя и для любого заданного контекста и имени можно определить — содержит ли данный контекст свойство с данным именем. Эта возможность используется при выяснении пригодности заданного контекста как среды для жизни некоторого объекта с определенными требованиями к наличию автоматических сервисов,