Unity 派生类中的拦截

发布于 2024-12-02 09:47:31 字数 2194 浏览 1 评论 0原文

我遇到了一种情况,当我使用派生类时,策略注入不再起作用。

涉及的类如下所示(基本上是一个接口、一个抽象基类和一个实现类):

public interface IRepository<T>
{
    void Create(T iItem);
}

public abstract class ElmtRepository<T> : IRepository<T>
{
    protected List<T> Items { get; set; }

    public ElmtRepository()
    {
        Items = new List<T>();
    }

    public void Create(T iItem)
    {
        Items.Add(iItem);
    }
}

public class AcctPgmRepository : ElmtRepository<AcctPgm>
{
}

配置如下所示:

  <container>
    <extension type="Interception"/>
    <register type="IRepository[AcctPgm]" mapTo="AcctPgmRepository">
      <interceptor type="InterfaceInterceptor"/>
      <interceptionBehavior type="PolicyInjectionBehavior"/>
    </register>
    <interception>
      <policy name="policy-create">
        <matchingRule name="create-rule1" type="TypeMatchingRule">
          <constructor>
            <param name="typeName">
              <value value="AcctPgmRepository"/>
            </param>
          </constructor>
        </matchingRule>
        <matchingRule name="create-rule2" type="MemberNameMatchingRule">
          <constructor>
            <param name="namesToMatch">
              <array type="string[]">
                <value value="Create"/>
              </array>
            </param>
          </constructor>
        </matchingRule>
        <callHandler name="create-handler1" type="AcctPgmAuthorizationHandler">
          <lifetime type="singleton"/>
          <constructor>
            <param name="allowedRoles">
              <array type="string[]">
                <value value="GroupController"/>
              </array>
            </param>
          </constructor>
        </callHandler>
      </policy>
    </interception>
  </container>

如果我删除 ElmtRepository 基类,它会按预期工作。对于基类,注入不会发生。没有错误消息,但也没有策略。即使我在派生类中实现 Create() 方法,也会发生这种情况。

有没有办法让这种类层次结构与 Unity 策略注入一起工作?

谢谢, 吉姆

I've got a situation where policy injection no longer works when I'm using a derived class.

The classes involved look like this (basically an interface, an abstract base class, and an implementation class):

public interface IRepository<T>
{
    void Create(T iItem);
}

public abstract class ElmtRepository<T> : IRepository<T>
{
    protected List<T> Items { get; set; }

    public ElmtRepository()
    {
        Items = new List<T>();
    }

    public void Create(T iItem)
    {
        Items.Add(iItem);
    }
}

public class AcctPgmRepository : ElmtRepository<AcctPgm>
{
}

The configuration looks like this:

  <container>
    <extension type="Interception"/>
    <register type="IRepository[AcctPgm]" mapTo="AcctPgmRepository">
      <interceptor type="InterfaceInterceptor"/>
      <interceptionBehavior type="PolicyInjectionBehavior"/>
    </register>
    <interception>
      <policy name="policy-create">
        <matchingRule name="create-rule1" type="TypeMatchingRule">
          <constructor>
            <param name="typeName">
              <value value="AcctPgmRepository"/>
            </param>
          </constructor>
        </matchingRule>
        <matchingRule name="create-rule2" type="MemberNameMatchingRule">
          <constructor>
            <param name="namesToMatch">
              <array type="string[]">
                <value value="Create"/>
              </array>
            </param>
          </constructor>
        </matchingRule>
        <callHandler name="create-handler1" type="AcctPgmAuthorizationHandler">
          <lifetime type="singleton"/>
          <constructor>
            <param name="allowedRoles">
              <array type="string[]">
                <value value="GroupController"/>
              </array>
            </param>
          </constructor>
        </callHandler>
      </policy>
    </interception>
  </container>

If I remove the ElmtRepository base class, it works as expected. With the base class, the injection doesn't happen. No error messages, but no policies either. This happens even if I implement the Create() method in the derived class.

Is there a way to make this sort of class hierarchy work with Unity policy injection?

Thanks,
Jim

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

谁把谁当真 2024-12-09 09:47:31

Unity 的这种类继承通常不会有问题。然而,配置泛型会带来无尽的麻烦,而且错误消息也很糟糕。我敢打赌这就是你真正的问题。但是,由于您没有发布错误消息(或 AcctPgm 类或 AcctPgmAuthorizationHandler),我无法确定。

我将包含的类型更改为 int 并让此版本的代码正常工作:

using System;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Practices.Unity.InterceptionExtension;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;

namespace UnityTest
{
    public interface IRepository<T>
    {
        void Create(T iItem);
    }

    public abstract class ElmtRepository<T> : IRepository<T>
    {
        protected List<T> Items { get; set; }

        public ElmtRepository()
        {
            Items = new List<T>();
        }

        public void Create(T iItem)
        {
            System.Diagnostics.Debug.WriteLine("Creating...");
            Items.Add(iItem);
        }
    }

    public class AcctPgmRepository : ElmtRepository<int> { }

    public class LogHandler : ICallHandler
    {
        public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
        {
            System.Diagnostics.Debug.WriteLine("Begin");
            IMethodReturn result = getNext().Invoke(input, getNext);
            System.Diagnostics.Debug.WriteLine("End");
            return result;
        }
        public int Order { get; set; }
    }

    [TestClass]
    public class InheritenceGenericsTests
    {
        [TestMethod]
        public void CreateTest()
        {
            IUnityContainer container = new UnityContainer().LoadConfiguration("Inheritence");
            IRepository<int> r2 = container.Resolve<IRepository<int>>();
            Assert.IsNotNull(r2);
            r2.Create(2);
        }
    }
}

使用配置:

<alias alias="IRepository" type="UnityTest.IRepository`1, UnityTest"/>
<alias alias="IRepositoryClosed" type="UnityTest.IRepository`1[System.Int32], UnityTest"/>
<alias alias="AcctPgmRepository" type="UnityTest.AcctPgmRepository, UnityTest"/>

<container name="Inheritence">
  <extension type="Interception"/>
  <!-- register either type="IRepositoryClosed" or type="IRepository" -->
  <register type="IRepositoryClosed" mapTo="AcctPgmRepository">
    <interceptor type="InterfaceInterceptor"/>
    <policyInjection/>
  </register>
  <interception>
    <policy name="policy-create">
      <matchingRule name="create-rule2" type="MemberNameMatchingRule">
        <constructor>
          <param name="namesToMatch">
            <array type="string[]">
              <value value="Create"/>
            </array>
          </param>
        </constructor>
      </matchingRule>
      <callHandler name="create-handler1" type="UnityTest.LogHandler, UnityTest"></callHandler>
    </policy>
  </interception>
</container>

给出输出:

Begin
Creating...
End

This kind of class inheritance Unity usually does without a problem. However configuring generics is endless headaches with poor error messages. I bet that’s your real problem. However since you didn’t post your error message (or the AcctPgm class, or the AcctPgmAuthorizationHandler) I can’t be sure.

I changed the contained type to int and got this version of your code working:

using System;
using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Practices.Unity.InterceptionExtension;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.Configuration;

namespace UnityTest
{
    public interface IRepository<T>
    {
        void Create(T iItem);
    }

    public abstract class ElmtRepository<T> : IRepository<T>
    {
        protected List<T> Items { get; set; }

        public ElmtRepository()
        {
            Items = new List<T>();
        }

        public void Create(T iItem)
        {
            System.Diagnostics.Debug.WriteLine("Creating...");
            Items.Add(iItem);
        }
    }

    public class AcctPgmRepository : ElmtRepository<int> { }

    public class LogHandler : ICallHandler
    {
        public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
        {
            System.Diagnostics.Debug.WriteLine("Begin");
            IMethodReturn result = getNext().Invoke(input, getNext);
            System.Diagnostics.Debug.WriteLine("End");
            return result;
        }
        public int Order { get; set; }
    }

    [TestClass]
    public class InheritenceGenericsTests
    {
        [TestMethod]
        public void CreateTest()
        {
            IUnityContainer container = new UnityContainer().LoadConfiguration("Inheritence");
            IRepository<int> r2 = container.Resolve<IRepository<int>>();
            Assert.IsNotNull(r2);
            r2.Create(2);
        }
    }
}

with config:

<alias alias="IRepository" type="UnityTest.IRepository`1, UnityTest"/>
<alias alias="IRepositoryClosed" type="UnityTest.IRepository`1[System.Int32], UnityTest"/>
<alias alias="AcctPgmRepository" type="UnityTest.AcctPgmRepository, UnityTest"/>

<container name="Inheritence">
  <extension type="Interception"/>
  <!-- register either type="IRepositoryClosed" or type="IRepository" -->
  <register type="IRepositoryClosed" mapTo="AcctPgmRepository">
    <interceptor type="InterfaceInterceptor"/>
    <policyInjection/>
  </register>
  <interception>
    <policy name="policy-create">
      <matchingRule name="create-rule2" type="MemberNameMatchingRule">
        <constructor>
          <param name="namesToMatch">
            <array type="string[]">
              <value value="Create"/>
            </array>
          </param>
        </constructor>
      </matchingRule>
      <callHandler name="create-handler1" type="UnityTest.LogHandler, UnityTest"></callHandler>
    </policy>
  </interception>
</container>

Gives output:

Begin
Creating...
End
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文