【问题标题】:ICallHandler, is an interface and cannot be constructedICallHandler,是一个接口,不能构造
【发布时间】:2015-07-25 08:55:50
【问题描述】:

在下面的代码中,我得到了错误ICallHandler,是一个接口,在解析对象时无法构造

            var attributePolicy = new AttributeDrivenPolicy();
            var rulePolicy = new RuleDrivenPolicy("LoggingFlyGoreJumpSleepMethodPolicy", new IMatchingRule[] { new MemberNameMatchingRule(new string[] { "Fly", "Gore", "Jump", "Sleep" }), new AssemblyMatchingRule("Domain") }, new string[] { "LoggingCallHandler", "CounterCallHandler" });
            var interceptor = new InterfaceInterceptor();
            var policies = new InjectionPolicy[] { attributePolicy, rulePolicy };
            var request = new CurrentInterceptionRequest(interceptor, typeof(IMosquito), mosquito.GetType());
            var behaviour = new PolicyInjectionBehavior(request, policies, _container); // *(1) we need a container just to resolve the LoggingCallHandler and CounterCallHandler
            var proxyMosquito = Intercept.ThroughProxy<IMosquito>(mosquito, interceptor, new IInterceptionBehavior[] { behaviour });
            proxyMosquito.Eat();
            proxyMosquito.Sleep();
            proxyMosquito.Suck();

我无法使用 RuleDrivenPolicy 但是 如果我按照下面的代码删除 RuleDrivenPolicy,它将运行

    var attributePolicy = new AttributeDrivenPolicy();
    var interceptor = new InterfaceInterceptor();
    var policies = new InjectionPolicy[] { attributePolicy };
    var request = new CurrentInterceptionRequest(interceptor, typeof(IMosquito), mosquito.GetType());
    var behaviour = new PolicyInjectionBehavior(request, policies, null); // *(2) container removed
    var proxyMosquito = Intercept.ThroughProxy<IMosquito>(mosquito, interceptor, new IInterceptionBehavior[] { behaviour });
    proxyMosquito.Eat();
    proxyMosquito.Sleep();
    proxyMosquito.Suck();

正在输出...

Mosquito Eating...
Mosquito Sleeping...
LoggingCallHandler Invoking Suck at 12:36:29
Mosquito Sucking...

但是,我希望应用策略规则。如果应用了策略规则,输出应该就像我不会使用 Intercept.ThroughProxy 方法

下面代码的不同输出,我使用容器来解析对象,而不是通过 Intercept.ThroughProxy 方法来解析对象..

 var proxyMosquito = _container.Resolve<IMosquito>();
    proxyMosquito.Eat();
    proxyMosquito.Sleep();
    proxyMosquito.Suck();

然后输出是..

Mosquito Eating...
LoggingCallHandler Invoking Sleep at 12:43:07
Mosquito Sleeping...
LoggingCallHandler Invoking Suck at 12:43:08
Mosquito Sucking...

容器有以下注册..

+ IUnityContainer '[default]' Container
+ IMatchingRule -> MemberNameMatchingRule 'Member Name Matching Rule-LoggingFlyGoreJumpSleepMethodPolicy' Transient
+ IMatchingRule -> AssemblyMatchingRule 'Assembly Matching Rule-LoggingFlyGoreJumpSleepMethodPolicy' Transient
+ ICallHandler -> LoggingCallHandler 'LoggingCallHandler-LoggingFlyGoreJumpSleepMethodPolicy' ContainerControlled
+ ICallHandler -> CounterCallHandler 'CounterCallHandler-LoggingFlyGoreJumpSleepMethodPolicy' ContainerControlled
+ InjectionPolicy -> RuleDrivenPolicy 'LoggingFlyGoreJumpSleepMethodPolicy' Transient
+ InjectionPolicy 'Microsoft.Practices.Unity.InterceptionExtension.AttributeDrivenPolicy, Microsoft.Practices.Unity.Interception, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' ContainerControlled
+ IServiceLocator '[default]' ExternallyControlled
+ IMosquito -> Mosquito '[default]' Transient
+ ExceptionManager '[default]' Transient
+ Database '[default]' Transient
+ ValidatorFactory '[default]' ContainerControlled

下面是实现的基础

 public class Mosquito : IMosquito
    {

        public void Bit()
        {
            Console.WriteLine("Mosquito Biting...");
        }

        public void Eat()
        {
            Console.WriteLine("Mosquito Eating...");
        }

        public void Sleep()
        {
            Console.WriteLine("Mosquito Sleeping...");
        }

        [LoggingCallHandler(1)]
        public void Suck()
        {
            Console.WriteLine("Mosquito Sucking...");
        }
    }

    public interface IMosquito : IAnimal
    {
        void Suck();
    }

    public interface IAnimal
    {
        void Eat();
        void Sleep();
    }

    [ConfigurationElementType(typeof(CustomCallHandlerData))]
    public class LoggingCallHandler : ICallHandler
    {
        public LoggingCallHandler(NameValueCollection attributes)
        {

        }

        public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
        {
            if (getNext == null) throw new ArgumentNullException("getNext");

            Console.WriteLine("LoggingCallHandler Invoking {0} at {1}", input.MethodBase.Name, DateTime.Now.ToLongTimeString());
            return getNext()(input, getNext);
        }

        public IEnumerable<Type> GetRequiredInterfaces()
        {
            return Type.EmptyTypes;
        }

        public int Order { get; set; }
    }

    public class LoggingCallHandlerAttribute : HandlerAttribute
    {
        private readonly int _order;

        public LoggingCallHandlerAttribute(int order)
        {
            _order = order;
        }

        public override ICallHandler CreateHandler(IUnityContainer container)
        {
            return new LoggingCallHandler(new NameValueCollection()) { Order = _order };
        }
    }

 <?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>
    <extension type="Interception" />
    <register type="Domain.IMosquito, Domain" mapTo="Domain.Mosquito, Domain">
      <interceptor type="InterfaceInterceptor" />
      <policyInjection />
    </register>
  </container>
</unity>


<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="policyInjection" type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.Configuration.PolicyInjectionSettings, Microsoft.Practices.EnterpriseLibrary.PolicyInjection" requirePermission="true" />
  </configSections>
  <policyInjection>
    <policies>
      <add name ="LoggingFlyGoreJumpSleepMethodPolicy">
        <matchingRules>
          <add name="Member Name Matching Rule" type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.MatchingRules.MemberNameMatchingRule, Microsoft.Practices.EnterpriseLibrary.PolicyInjection">
            <matches>
              <add match="Fly" />
              <add match="Gore" />
              <add match="Jump" />
              <add match="Sleep" />
            </matches>
          </add>
          <add name="Assembly Matching Rule" match="Domain" type="Microsoft.Practices.EnterpriseLibrary.PolicyInjection.MatchingRules.AssemblyMatchingRule, Microsoft.Practices.EnterpriseLibrary.PolicyInjection"/>
        </matchingRules>
        <handlers>
          <add name="LoggingCallHandler" order="1" type="IoCnAOP.LoggingCallHandler, IoCnAOP" />
        </handlers>
      </add>
    </policies>
  </policyInjection>
</configuration>

【问题讨论】:

    标签: c# dependency-injection enterprise-library


    【解决方案1】:

    我不能 100% 确定您的具体情况,因为没有显示容器注册码,而且我不确定配置代码的来源。

    但是,问题似乎在于调用处理程序的注册方式。调用处理程序的名称(不是类名)是传递给 RuleDrivenPolicy 的内容。您正在传递“LoggingCallHandler”,但容器的注册是针对“LoggingCallHandler-LoggingFlyGoreJumpSleepMethodPolicy”的。

    如果你对齐命名,那么它应该可以工作。

    var interceptor = new InterfaceInterceptor();
    
    var rulePolicy = new RuleDrivenPolicy("LoggingFlyGoreJumpSleepMethodPolicy",
        new IMatchingRule[] { new MemberNameMatchingRule(new string[] { "Fly", "Gore", "Jump", "Sleep" }) },
        new string[] { "LoggingCallHandler-LoggingFlyGoreJumpSleepMethodPolicy" });
    
    var policies = new InjectionPolicy[] { rulePolicy };
    var request = new CurrentInterceptionRequest(interceptor, typeof(IMosquito), mosquito.GetType());
    var behaviour = new PolicyInjectionBehavior(request, policies, container); 
    var proxyMosquito = Intercept.ThroughProxy<IMosquito>(mosquito, interceptor, new IInterceptionBehavior[] { behaviour });
    proxyMosquito.Eat();
    proxyMosquito.Sleep();
    proxyMosquito.Suck();
    

    这将显示:

    蚊子吃...
    LoggingCallHandler 在上午 11:39:35 调用睡眠
    蚊子睡觉...
    吸蚊子……

    显示 Sleep 被拦截,因为这是我们调用的唯一方法,我们为其设置了匹配规则。

    另外,我正在使用编程配置,我必须向 LoggingCallHandler 添加一个默认构造函数并告诉 Unity 使用该构造函数(因为 Unity 不知道如何在没有注册的情况下解析 NameValueCollection)。如果使用配置,您可能不会遇到这个问题。

    【讨论】:

    • 顺便说一句,我试图找出在通过 EF 或企业数据检索的实体上注入 AOP 方面的最佳工作流程。我们从标准存储库中获取 RAW 实体,但哪个是获取已应用 AOP 方面的最佳工作流程?工作流问题是.. Intercept.ThroughProxy 将 AOP 方面包装在现有对象或实体上,但结果不是兼容实体,因为代理实体 Intercept.NewInstance 创建一个新实体但不包装任何现有实体我们会从 EF 或 Enterprise Data 中检索到的数据
    • 应用 LINQ 转换来创建新的 AOP 包装对象将导致新包装的对象从 EF DbContext 中分离出来(因为数据块不介意,因为它没有长时间运行跟踪实体更改的上下文)一种有效的方法可能是订阅 ObjectContext 公共事件 ObjectMaterializedEventHandler ObjectMaterialized;当从数据源中的数据创建新实体对象时发生的事件,作为查询或加载操作的一部分和包装在 AOP 方面,给定实体具有派生(但不是代理)兼容实体
    猜你喜欢
    • 2017-09-26
    • 1970-01-01
    • 1970-01-01
    • 2017-08-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-04
    • 2011-11-05
    相关资源
    最近更新 更多