惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

WordPress大学
WordPress大学
Spread Privacy
Spread Privacy
T
The Exploit Database - CXSecurity.com
Simon Willison's Weblog
Simon Willison's Weblog
P
Privacy & Cybersecurity Law Blog
L
LINUX DO - 热门话题
T
Threat Research - Cisco Blogs
T
Tenable Blog
TaoSecurity Blog
TaoSecurity Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
AI
AI
P
Proofpoint News Feed
A
About on SuperTechFans
P
Privacy International News Feed
月光博客
月光博客
雷峰网
雷峰网
S
Secure Thoughts
博客园 - 叶小钗
博客园 - 聂微东
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Project Zero
Project Zero
The Cloudflare Blog
SecWiki News
SecWiki News
The Hacker News
The Hacker News
V
Vulnerabilities – Threatpost
罗磊的独立博客
A
Arctic Wolf
阮一峰的网络日志
阮一峰的网络日志
Know Your Adversary
Know Your Adversary
酷 壳 – CoolShell
酷 壳 – CoolShell
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
T
Troy Hunt's Blog
The Last Watchdog
The Last Watchdog
Schneier on Security
Schneier on Security
小众软件
小众软件
有赞技术团队
有赞技术团队
博客园 - 司徒正美
T
Tailwind CSS Blog
量子位
C
Cybersecurity and Infrastructure Security Agency CISA
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
Hugging Face - Blog
Hugging Face - Blog
人人都是产品经理
人人都是产品经理
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
S
Security @ Cisco Blogs
大猫的无限游戏
大猫的无限游戏
S
SegmentFault 最新的问题
Apple Machine Learning Research
Apple Machine Learning Research
宝玉的分享
宝玉的分享
L
Lohrmann on Cybersecurity

博客园 - 望天

Web 2.0 网站架构不可或缺的图书 值得收藏的146条民间小偏方 回龙观常用电话 AJAX页面呈现模式选择 AJAX富客户端开发 Ajax框架介绍 EBS架构及实现业务特点 ASP.net 大文件上传 实现 架构师要了解那些?? witLuo介绍 网络负载平衡转发技术简介(转载) 双网卡实现负载均衡技术的实现与原理 Server Application Unavailable 事务处理可选方式 C# 注册COM+组件步骤 在分布式事务中登记时出错 由TObject原码对类的内存分配 TOrderedList类 TStream类
AOP方法调用消息截获(之realproxy)
望天 · 2006-11-16 · via 博客园 - 望天

        实现消息截获,我们熟知的方法有将需要监控的类型从 ContextBandObject类派生,从而用消息截获器实行对 对象的横向监控。 以下是另一种简单的实行对象调用的监控AOP技术实现;

1. 调用代码例子


2. 源代码实现

/// <summary>
/// Executes both standalone and transacted SQL queries described by strongly-typed interface.
/// </summary>
/// <typeparam name="T">Interface with function prototypes</typeparam>
/// <exception cref="System.ArgumentException">Thrown when there is an error in prototype description.</exception>
/// <exception cref="System.Data.SqlClient.SqlException">Error from SQL Server while executing query.</exception>
public sealed class SqlQuery<T> : RealProxy where T : class
{
private readonly SqlConnection connection;
private readonly SqlTransaction transaction;
private readonly bool closeConnection;
public static T Create(SqlConnection connection)
{
return (new SqlQuery<T>(connection, null)).GetTransparentProxy() as T;
}
public static T Create(SqlTransaction transaction)
{
return (new SqlQuery<T>(transaction.Connection, transaction)).GetTransparentProxy() as T;
}
public static T Create(string connectionString)
{
return (new SqlQuery<T>(connectionString)).GetTransparentProxy() as T;
}
private SqlQuery(SqlConnection conn, SqlTransaction tran) : base(typeof(T))
{
connection = conn;
transaction = tran;
closeConnection = false;
}
private SqlQuery(string connectionString) : base(typeof(T))
{
connection = new SqlConnection(connectionString);
transaction = null;
closeConnection = true;
}
[DebuggerStepThrough]
public override IMessage Invoke(IMessage msg)
{
IMethodCallMessage method = msg as IMethodCallMessage;
if (method == null)
throw new ArgumentException("Failed to cast IMessage to IMethodCallMessage");
if (method.HasVarArgs)
throw new ArgumentException("Variable arguments are not supprted by SQL Server");
MethodInfo mi = (MethodInfo)method.MethodBase;
Type t = mi.ReturnType;
bool Void = (t == null || t.FullName == "System.Void");
SqlParameterCacheEntry entry = SqlParameterCache.GetEntry(mi);
using (SqlCommand cmd = connection.CreateCommand())
{
cmd.Transaction = transaction;
cmd.CommandType = entry.CommandType;
cmd.CommandText = entry.CommandText;
SqlParameter[] parameters = entry.GetParameters();
int i = -1;
int recordsAffected = -1;
int argCount = method.ArgCount;
object recordsSelected = null;
foreach (SqlParameter p in parameters)
{
cmd.Parameters.Add(p);
if (entry.ReturnsValue && p.ParameterName.StartsWith("@")) continue;
if (++i >= argCount)
throw new ArgumentException("Too many parameters passed");
if (!p.ParameterName.Equals(method.GetArgName(i), StringComparison.InvariantCultureIgnoreCase))
throw new ArgumentException("Parameter name \'" + p.ParameterName +
"\' does not match defined name", method.GetArgName(i));
if (p.Direction == ParameterDirection.ReturnValue) continue;
if (p.Direction == ParameterDirection.Output) continue;
object value = method.Args[i];
if (value is IDbDataParameter)
{
IDbDataParameter dbp = (IDbDataParameter)value;
p.Value = (dbp.Value == null) ? DBNull.Value : dbp.Value;
}
else
p.Value = (value == null) ? DBNull.Value : value;
}
if (i < argCount - 1)
throw new ArgumentException("Not enough parameters passed");
List<object> outParams = new List<object>(method.ArgCount);
try
{
if (closeConnection)
connection.Open();
if (entry.ReturnsRecordset)
{
bool singleRow = false;
CommandBehavior opts = CommandBehavior.Default;
if (t == typeof(DataSet))
recordsSelected = new DataSet();
else if (t == typeof(DataTable))
opts = CommandBehavior.SingleResult;
else if (t == typeof(SingleRowDataTable))
{
opts = CommandBehavior.SingleResult | CommandBehavior.SingleRow;
singleRow = true;
}
else
throw new ArgumentException("DataSet, DataTable or SingleRowDataTable must be returned", "Return value");
using (SqlDataReader rd = cmd.ExecuteReader(opts))
{
if (!singleRow)
{
do
{
DataColumn[] columns = GetColumnInfo(rd);
object[] values = new object[columns.Length];
DataTable table = new DataTable();
table.BeginLoadData();
table.Columns.AddRange(columns);
while (rd.Read())
{
rd.GetValues(values);
table.Rows.Add(values);
}
table.EndLoadData();
table.AcceptChanges();
if (recordsSelected != null && recordsSelected is DataSet)
((DataSet)recordsSelected).Tables.Add(table);
else
{
recordsSelected = table;
break;
}
}
while (rd.NextResult());
}
else
{
DataColumn[] columns = GetColumnInfo(rd);
object[] values = new object[columns.Length];
SingleRowDataTable table = new SingleRowDataTable();
table.BeginLoadData();
table.Columns.AddRange(columns);
if (rd.Read())
{
rd.GetValues(values);
table.Rows.Add(values);
}
table.EndLoadData();
table.AcceptChanges();
recordsSelected = table;
}
rd.Close();
}
}
else
{
recordsAffected = cmd.ExecuteNonQuery();
}
for (int j = 0; j < method.ArgCount; j++)
{
SqlParameter p = cmd.Parameters[method.GetArgName(j)];
outParams.Add(((p.Direction == ParameterDirection.Input || p.Value == DBNull.Value) ? null : p.Value));
}
}
finally
{
if (closeConnection)
connection.Close();
}
if (entry.ReturnsRecordset)
return new ReturnMessage(recordsSelected, outParams.ToArray(), outParams.Count, method.LogicalCallContext, method);
if (entry.ReturnsValue)
{
object value = cmd.Parameters[entry.ReturnParameter].Value;
if (value == DBNull.Value) value = null;
return new ReturnMessage(value, outParams.ToArray(), outParams.Count, method.LogicalCallContext, method);
}
else if (Void)
return new ReturnMessage(null, outParams.ToArray(), outParams.Count, method.LogicalCallContext, method);
else if (t == typeof(int))
return new ReturnMessage(recordsAffected, outParams.ToArray(), outParams.Count, method.LogicalCallContext, method);
throw new ArgumentException("Method must return SqlReturn-marked value, DataSet, DataTable, SingleRowDataTable, Int or Void", "Return value");
}
}