TypeMatchingRule XML配置解析类类型而不是实现的接口

时间:2015-07-30 13:42:45

标签: c# dependency-injection enterprise-library

我正在根据自己的需要调整找到的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>

如果该类实现了接口IDirty,则问题位于 match =&#34; IoCnAOP.IDirty&#34; 不匹配 (但是,如果我将其更改为follow match =&#34; Domain.Frog&#34;,我的意思是使用类类型然后它可以工作,但这不是我要求的要求。我想匹配如果类实现给定的接口IDirty)

所以...如果我调整了流畅的API代码可以正常工作......但是XML配置只能解析类类型...... 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>

1 个答案:

答案 0 :(得分:1)

配置使用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传递目标类型。对于程序化使用,请使用Type构造函数。