TypeMatchingRule XML 配置解析 class 类型而不是实现的接口
TypeMatchingRule XML configuration resolves the class type instead of implemented interface
我正在根据自己的需要调整找到的代码 http://www.christophdebaene.com/blog/2008/11/02/aop-in-action-part-1-dirty-tracking-using-unity-interception/
我想将我的 Unity 流利 API 改编代码部分从 Unity 翻译到企业库策略 XML 配置
从这个工作流利API…
.AddNewExtension<Interception>()
.RegisterInstance<ICallHandler>("DirtyCallHandler", new DirtyCallHandler(null))
.Configure<Interception>()
.AddPolicy("DirtyPolicy")
.AddMatchingRule(new PropertyMatchingRule("*", PropertyMatchingOption.Set))
.AddMatchingRule(new CustomAttributeMatchingRule(typeof(DirtyAttribute), true))
.AddMatchingRule(new InstanceOfMatchingRule(typeof(IDirty)))
.AddCallHandler("DirtyCallHandler")
这个XML配置…
<policies>
<add name="DirtyPolicy">
<matchingRules>
<add name="SetPropertyRule" type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.MatchingRules.PropertyMatchingRule, Microsoft.Practices.EnterpriseLibrary.PolicyInjection">
<matches>
<add matchOption="Set" match="*" />
</matches>
</add>
<add name="DirtyAttributeRule" attributeType="IoCnAOP.DirtyAttribute, IoCnAOP" searchInheritanceChain="true" type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.MatchingRules.CustomAttributeMatchingRule, Microsoft.Practices.EnterpriseLibrary.PolicyInjection"/>
<add name="InstanceOfIDirtyRule" type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.MatchingRules.TypeMatchingRule, Microsoft.Practices.EnterpriseLibrary.PolicyInjection">
<matches>
<add match=" IoCnAOP.IDirty" ignoreCase="false"/>
</matches>
</add>
</matchingRules>
<handlers>
<add name="DirtyCallHandler" order="0" type="IoCnAOP.DirtyCallHandler, IoCnAOP" />
</handlers>
</add>
</policies>
问题出在match="IoCnAOP.IDirty"如果class实现接口IDirty不匹配
(但是,如果我将其更改为 match="Domain.Frog",我的意思是使用 class 类型,那么它就可以工作,但这不是我正在寻找的要求。如果 class 实现了给定的接口 IDirty)
所以……如果我改编的流利的 API 代码工作正常……但是 XML 配置只解析 class 类型.. XML 上遗漏了一些东西配置
如何改用 XML 使其正常工作?
非常感谢
BR
(下面是一些相关的代码摘录……)
public interface IDirty
{
bool IsDirty { get; set; }
}
public class Frog : IDirty
{
public bool IsDirty { get; set; }
public virtual string JustAProperty { get; [Dirty]set; }
}
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class DirtyAttribute : Attribute
{
}
public class InstanceOfMatchingRule : IMatchingRule
{
private readonly Type _type;
public InstanceOfMatchingRule(Type type)
{
_type = type;
}
public bool Matches(System.Reflection.MethodBase member)
{
return _type.IsAssignableFrom(member.DeclaringType);
}
}
[ConfigurationElementType(typeof(CustomCallHandlerData))]
public class DirtyCallHandler : ICallHandler
{
public DirtyCallHandler(NameValueCollection attributes)
{
}
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
if (getNext == null)
throw new ArgumentNullException("getNext");
Console.WriteLine("DirtyCallHandle Invoking {0} at {1}", input.MethodBase.Name, DateTime.Now.ToLongTimeString());
IsDirty(input.Target, input.MethodBase, input.Arguments[0]);
return getNext()(input, getNext);
}
public int Order { get; set; }
private static void IsDirty(object target, MethodBase methodBase, object value) //http://www.christophdebaene.com/blog/2008/11/02/aop-in-action-part-1-dirty-tracking-using-unity-interception/
{
if (((IDirty)target).IsDirty)
return;
var propertyName = methodBase.Name.Substring("set_".Length);
var info = target.GetType().GetProperty(propertyName);
if (info == null)
return;
var oldValue = info.GetValue(target, null);
if (!IsEqual(value, oldValue))
((IDirty)target).IsDirty = true;
}
private static bool IsEqual(object valueX, object valueY)
{
if (valueX == null && valueY != null)
return false;
if (valueX != null && valueY == null)
return false;
return valueX == null || valueX.Equals(valueY);
}
}
<?xml version="1.0" encoding="utf-8" ?>
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration" />
<container>
<register type="Domain.Frog, Domain">
<interceptor type="VirtualMethodInterceptor" />
<policyInjection />
</register>
</container>
</unity>
配置使用 Microsoft.Practices.EnterpriseLibrary.PolicyInjection.MatchingRules.TypeMatchingRule
,它直接匹配类型而不是您的自定义 InstanceOfMatchingRule
。
通过 XML 配置公开 InstanceOfMatchingRule 的最简单方法是使用内置的 CustomMatchingRuleData:
[ConfigurationElementType(typeof(CustomMatchingRuleData))]
public class InstanceOfMatchingRule : IMatchingRule
{
private readonly Type _type;
public InstanceOfMatchingRule(NameValueCollection configuration)
{
_type = Type.GetType(configuration["targetType"]);
}
public InstanceOfMatchingRule(Type targetType)
{
_type = targetType;
}
public bool Matches(System.Reflection.MethodBase member)
{
return _type.IsAssignableFrom(member.DeclaringType);
}
}
然后使用配置:
<policyInjection>
<policies>
<add name="DirtyPolicy">
<matchingRules>
<add targetType="IoCnAOP.IDirty" type="IoCnAOP.InstanceOfMatchingRule, IoCnAOP, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
name="InstanceOfIDirtyRule" />
</matchingRules>
<handlers>
<add name="DirtyCallHandler" order="0" type="IoCnAOP.DirtyCallHandler, IoCnAOP" />
</handlers>
</add>
</policies>
</policyInjection>
通过 NameValueCollection 传入目标类型。对于编程用途,请使用类型构造函数。
我正在根据自己的需要调整找到的代码 http://www.christophdebaene.com/blog/2008/11/02/aop-in-action-part-1-dirty-tracking-using-unity-interception/
我想将我的 Unity 流利 API 改编代码部分从 Unity 翻译到企业库策略 XML 配置
从这个工作流利API…
.AddNewExtension<Interception>()
.RegisterInstance<ICallHandler>("DirtyCallHandler", new DirtyCallHandler(null))
.Configure<Interception>()
.AddPolicy("DirtyPolicy")
.AddMatchingRule(new PropertyMatchingRule("*", PropertyMatchingOption.Set))
.AddMatchingRule(new CustomAttributeMatchingRule(typeof(DirtyAttribute), true))
.AddMatchingRule(new InstanceOfMatchingRule(typeof(IDirty)))
.AddCallHandler("DirtyCallHandler")
这个XML配置…
<policies>
<add name="DirtyPolicy">
<matchingRules>
<add name="SetPropertyRule" type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.MatchingRules.PropertyMatchingRule, Microsoft.Practices.EnterpriseLibrary.PolicyInjection">
<matches>
<add matchOption="Set" match="*" />
</matches>
</add>
<add name="DirtyAttributeRule" attributeType="IoCnAOP.DirtyAttribute, IoCnAOP" searchInheritanceChain="true" type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.MatchingRules.CustomAttributeMatchingRule, Microsoft.Practices.EnterpriseLibrary.PolicyInjection"/>
<add name="InstanceOfIDirtyRule" type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.MatchingRules.TypeMatchingRule, Microsoft.Practices.EnterpriseLibrary.PolicyInjection">
<matches>
<add match=" IoCnAOP.IDirty" ignoreCase="false"/>
</matches>
</add>
</matchingRules>
<handlers>
<add name="DirtyCallHandler" order="0" type="IoCnAOP.DirtyCallHandler, IoCnAOP" />
</handlers>
</add>
</policies>
问题出在match="IoCnAOP.IDirty"如果class实现接口IDirty不匹配 (但是,如果我将其更改为 match="Domain.Frog",我的意思是使用 class 类型,那么它就可以工作,但这不是我正在寻找的要求。如果 class 实现了给定的接口 IDirty)
所以……如果我改编的流利的 API 代码工作正常……但是 XML 配置只解析 class 类型.. XML 上遗漏了一些东西配置
如何改用 XML 使其正常工作?
非常感谢
BR
(下面是一些相关的代码摘录……)
public interface IDirty
{
bool IsDirty { get; set; }
}
public class Frog : IDirty
{
public bool IsDirty { get; set; }
public virtual string JustAProperty { get; [Dirty]set; }
}
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
public class DirtyAttribute : Attribute
{
}
public class InstanceOfMatchingRule : IMatchingRule
{
private readonly Type _type;
public InstanceOfMatchingRule(Type type)
{
_type = type;
}
public bool Matches(System.Reflection.MethodBase member)
{
return _type.IsAssignableFrom(member.DeclaringType);
}
}
[ConfigurationElementType(typeof(CustomCallHandlerData))]
public class DirtyCallHandler : ICallHandler
{
public DirtyCallHandler(NameValueCollection attributes)
{
}
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
if (getNext == null)
throw new ArgumentNullException("getNext");
Console.WriteLine("DirtyCallHandle Invoking {0} at {1}", input.MethodBase.Name, DateTime.Now.ToLongTimeString());
IsDirty(input.Target, input.MethodBase, input.Arguments[0]);
return getNext()(input, getNext);
}
public int Order { get; set; }
private static void IsDirty(object target, MethodBase methodBase, object value) //http://www.christophdebaene.com/blog/2008/11/02/aop-in-action-part-1-dirty-tracking-using-unity-interception/
{
if (((IDirty)target).IsDirty)
return;
var propertyName = methodBase.Name.Substring("set_".Length);
var info = target.GetType().GetProperty(propertyName);
if (info == null)
return;
var oldValue = info.GetValue(target, null);
if (!IsEqual(value, oldValue))
((IDirty)target).IsDirty = true;
}
private static bool IsEqual(object valueX, object valueY)
{
if (valueX == null && valueY != null)
return false;
if (valueX != null && valueY == null)
return false;
return valueX == null || valueX.Equals(valueY);
}
}
<?xml version="1.0" encoding="utf-8" ?>
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration" />
<container>
<register type="Domain.Frog, Domain">
<interceptor type="VirtualMethodInterceptor" />
<policyInjection />
</register>
</container>
</unity>
配置使用 Microsoft.Practices.EnterpriseLibrary.PolicyInjection.MatchingRules.TypeMatchingRule
,它直接匹配类型而不是您的自定义 InstanceOfMatchingRule
。
通过 XML 配置公开 InstanceOfMatchingRule 的最简单方法是使用内置的 CustomMatchingRuleData:
[ConfigurationElementType(typeof(CustomMatchingRuleData))]
public class InstanceOfMatchingRule : IMatchingRule
{
private readonly Type _type;
public InstanceOfMatchingRule(NameValueCollection configuration)
{
_type = Type.GetType(configuration["targetType"]);
}
public InstanceOfMatchingRule(Type targetType)
{
_type = targetType;
}
public bool Matches(System.Reflection.MethodBase member)
{
return _type.IsAssignableFrom(member.DeclaringType);
}
}
然后使用配置:
<policyInjection>
<policies>
<add name="DirtyPolicy">
<matchingRules>
<add targetType="IoCnAOP.IDirty" type="IoCnAOP.InstanceOfMatchingRule, IoCnAOP, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
name="InstanceOfIDirtyRule" />
</matchingRules>
<handlers>
<add name="DirtyCallHandler" order="0" type="IoCnAOP.DirtyCallHandler, IoCnAOP" />
</handlers>
</add>
</policies>
</policyInjection>
通过 NameValueCollection 传入目标类型。对于编程用途,请使用类型构造函数。