我们使用 UnityContainer 开源 ( https://github.com/unitycontainer ) 版本 5.11.1 进行 DI 和拦截。
web.config(示例)
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Unity.Configuration, Version=5.11.2.0, Culture=neutral, PublicKeyToken=489b6accfaf20ef0" />
</configSections>
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Unity.Interception.Configuration" />
<container>
<extension type="Interception"/>
<register type="Agility.Server.Core.Model.Interfaces.Repository.IResourceRepository, Agility.Server.Core.Model, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d86c87abe4a71948" mapTo="Agility.Server.Repository.SqlServer.ResourceRepository, Agility.Server.Repository.SqlServer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d86c87abe4a71948"/>
<register type="Agility.Server.Core.Model.Interfaces.Repository.IServerRepository, Agility.Server.Core.Model, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d86c87abe4a71948" mapTo="Agility.Server.Repository.SqlServer.ServerRepository, Agility.Server.Repository.SqlServer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d86c87abe4a71948"/>
<register type="Agility.Server.Core.Model.Interfaces.Repository.ITenantRepository, Agility.Server.Core.Model, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d86c87abe4a71948" mapTo="Agility.Server.Repository.SqlServer.TenantRepository, Agility.Server.Repository.SqlServer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d86c87abe4a71948"/>
<register type="Agility.Server.Core.Model.Interfaces.Repository.IThreadPoolRepository, Agility.Server.Core.Model, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d86c87abe4a71948" mapTo="Agility.Server.Repository.SqlServer.ThreadPoolRepository, Agility.Server.Repository.SqlServer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d86c87abe4a71948"/>
<register type="Agility.Server.Core.Model.Interfaces.Repository.IUserRepository, Agility.Server.Core.Model, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d86c87abe4a71948" mapTo="Agility.Server.Repository.SqlServer.UserRepository, Agility.Server.Repository.SqlServer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d86c87abe4a71948"/>
<register type="IMatchingRule" name="AllRule" mapTo="Agility.Server.Common.Logging.AlwaysMatchingRule, Agility.Server.Common, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d86c87abe4a71948" />
<register type="ICallHandler" name="LogHandler" mapTo="Agility.Server.Common.Logging.LogMethodCallHandler, Agility.Server.Common, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d86c87abe4a71948"/>
<interception>
<policy name="webMethods">
<matchingRule name="AllRule" />
<callHandler name="LogHandler" />
</policy>
</interception>
</unity>
.....
下面是 AlwaysMatchingRule 的代码
public class AlwaysMatchingRule : IMatchingRule
{
[InjectionConstructor]
public AlwaysMatchingRule()
{
}
public bool Matches(MethodBase member)
{
return true;
}
}
下面是 CallHandler 的代码
public class LogMethodCallHandler : ICallHandler
{
[InjectionConstructor]
public LogMethodCallHandler()
{
this.Order = 0;
}
public bool WillExecute
{
get { return true; }
}
public int Order { get; set; }
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
// Log method invoked, by default we don't log method inputs
bool logMethodInputs = false;
this.LogMethodInvoked(input, logMethodInputs);
// Invoke the next behavior in the chain.
IMethodReturn methodReturn = getNext()(input, getNext);
// Log method completed, by default we don't log method outputs
bool logMethodOutputs = false;
this.LogMethodCompleted(input, methodReturn, logMethodOutputs);
return methodReturn;
}
protected void LogMethodInvoked(IMethodInvocation methodInvocation, bool logMethodInputs)
{
ArgumentValidator.ValidateForNotNull("methodInvocation", methodInvocation);
// Before invoking the method on the original target.
Logger.Log(
LogMessage.InvokedMethod,
LogCategory.Information,
methodInvocation.MethodBase.DeclaringType,
methodInvocation.MethodBase.Name,
methodInvocation.MethodBase);
}
protected void LogMethodCompleted(
IMethodInvocation methodInvocation,
IMethodReturn methodReturn,
bool logMethodOutputs)
{
// After invoking the method on the original target, log the method completion
if (methodReturn.Exception != null)
{
// Log method exception
Logger.Log(
LogMessage.CompletedMethodWithException,
LogCategory.Information,
methodInvocation.MethodBase.DeclaringType,
methodInvocation.MethodBase.Name,
methodInvocation.MethodBase,
methodReturn.Exception);
// Log any inner exception
if (methodReturn.Exception.InnerException != null)
{
bool logAdditionalInformation = false;
Logger.Log(
LogMessage.InnerException,
LogCategory.Information,
logAdditionalInformation,
methodReturn.Exception.InnerException);
}
}
else
{
// Log method method completed
Logger.Log(
LogMessage.CompletedMethod,
LogCategory.Information,
methodInvocation.MethodBase.DeclaringType,
methodInvocation.MethodBase.Name,
methodInvocation.MethodBase);
}
}
}
它从不写入日志文件。我们尝试了其他方法并让它在单一类型上工作。
web.config 更改
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Unity.Configuration, Version=5.11.2.0, Culture=neutral, PublicKeyToken=489b6accfaf20ef0" />
</configSections>
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Unity.Interception.Configuration" />
<container>
<extension type="Interception"/>
<register type="Agility.Server.Core.Model.Interfaces.Repository.IResourceRepository, Agility.Server.Core.Model, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d86c87abe4a71948" mapTo="Agility.Server.Repository.SqlServer.ResourceRepository, Agility.Server.Repository.SqlServer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d86c87abe4a71948"/>
<register type="Agility.Server.Core.Model.Interfaces.Repository.IServerRepository, Agility.Server.Core.Model, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d86c87abe4a71948" mapTo="Agility.Server.Repository.SqlServer.ServerRepository, Agility.Server.Repository.SqlServer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d86c87abe4a71948"/>
<register type="Agility.Server.Core.Model.Interfaces.Repository.ITenantRepository, Agility.Server.Core.Model, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d86c87abe4a71948" mapTo="Agility.Server.Repository.SqlServer.TenantRepository, Agility.Server.Repository.SqlServer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d86c87abe4a71948"/>
<register type="Agility.Server.Core.Model.Interfaces.Repository.IThreadPoolRepository, Agility.Server.Core.Model, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d86c87abe4a71948" mapTo="Agility.Server.Repository.SqlServer.ThreadPoolRepository, Agility.Server.Repository.SqlServer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d86c87abe4a71948"/>
<register type="Agility.Server.Core.Model.Interfaces.Repository.IUserRepository, Agility.Server.Core.Model, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d86c87abe4a71948" mapTo="Agility.Server.Repository.SqlServer.UserRepository, Agility.Server.Repository.SqlServer, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d86c87abe4a71948">
<interceptor type="InterfaceInterceptor"/>
<interceptionBehavior type="Agility.Server.Common.Logging.LogMethodInterceptionBehavior, Agility.Server.Common, Version=1.0.0.0, Culture=neutral, PublicKeyToken=d86c87abe4a71948"/>
</register>
</unity>
.....
LogMethodInterceptionBehavior 代码
public class LogMethodInterceptionBehavior : IInterceptionBehavior
{
public bool WillExecute
{
get { return true; }
}
public IEnumerable<Type> GetRequiredInterfaces()
{
return Type.EmptyTypes;
}
public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext)
{
// Log method invoked, by default we don't log method inputs
bool logMethodInputs = false;
this.LogMethodInvoked(input, logMethodInputs);
// Invoke the next behavior in the chain.
IMethodReturn methodReturn = getNext()(input, getNext);
// Log method completed, by default we don't log method outputs
bool logMethodOutputs = false;
this.LogMethodCompleted(input, methodReturn, logMethodOutputs);
return methodReturn;
}
protected void LogMethodInvoked(IMethodInvocation methodInvocation, bool logMethodInputs)
{
ArgumentValidator.ValidateForNotNull("methodInvocation", methodInvocation);
// Before invoking the method on the original target.
Logger.Log(
LogMessage.InvokedMethod,
LogCategory.Information,
methodInvocation.MethodBase.DeclaringType,
methodInvocation.MethodBase.Name,
methodInvocation.MethodBase);
}
protected void LogMethodCompleted(
IMethodInvocation methodInvocation,
IMethodReturn methodReturn,
bool logMethodOutputs)
{
// After invoking the method on the original target, log the method completion
if (methodReturn.Exception != null)
{
// Log method exception
Logger.Log(
LogMessage.CompletedMethodWithException,
LogCategory.Information,
methodInvocation.MethodBase.DeclaringType,
methodInvocation.MethodBase.Name,
methodInvocation.MethodBase,
methodReturn.Exception);
// Log any inner exception
if (methodReturn.Exception.InnerException != null)
{
bool logAdditionalInformation = false;
Logger.Log(
LogMessage.InnerException,
LogCategory.Information,
logAdditionalInformation,
methodReturn.Exception.InnerException);
}
}
else
{
// Log method method completed
Logger.Log(
LogMessage.CompletedMethod,
LogCategory.Information,
methodInvocation.MethodBase.DeclaringType,
methodInvocation.MethodBase.Name,
methodInvocation.MethodBase);
}
}
}
方法的问题是我必须将它应用于所有我不想要的类型。有没有办法在一个地方做到这一点并将其应用于所有类型?
我可以使用策略注入方法或 Unity 拦截。
请注意,我希望通过 web.config 进行此操作。
谢谢,阿米特