6

プロジェクトを .Net 2 から .Net4.5 にアップグレードする作業を進めています。同時に、できるだけ多くの参照を NuGet にプッシュし、バージョンが最新であることを確認しています。

テストの 1 つを実行するのに問題があります

テストクラス:

        public class Person
    {
        public static int PersonBaseMethodHitCount { get; set; }
        public virtual void BaseMethod()
        {
            PersonBaseMethodHitCount = PersonBaseMethodHitCount + 1;
        }
        public static int PersonSomeMethodToBeOverriddenHitCount { get; set; }
        public virtual void SomeMethodToBeOverridden()
        {
            PersonSomeMethodToBeOverriddenHitCount = PersonSomeMethodToBeOverriddenHitCount + 1;
        }
    }

    public class Employee : Person
    {
        public static int EmployeeSomeMethodToBeOverriddenHitCount { get; set; }
        public override void SomeMethodToBeOverridden()
        {
            EmployeeSomeMethodToBeOverriddenHitCount = EmployeeSomeMethodToBeOverriddenHitCount + 1;
        }
        public static int EmployeeCannotInterceptHitCount { get; set; }
        public void CannotIntercept()
        {
            EmployeeCannotInterceptHitCount = EmployeeCannotInterceptHitCount + 1;
        }

        public virtual void MethodWithParameter(
            [SuppressMessage("a", "b"), InheritedAttribute, Noninherited]string foo)
        {
        }
    }

    public class MyInterceptor : IInterceptor
    {
        public static int HitCount { get; set; }
        public void Intercept(IInvocation invocation)
        {
            HitCount = HitCount + 1;
            invocation.Proceed();
        }
    }

テスト (このフィクスチャのセットアップはありません):

var container = new WindsorContainer();
        container.Register(Component.For<MyInterceptor>().ImplementedBy<MyInterceptor>());
        container.Register(
            Component
            .For<Employee>()
            .ImplementedBy<Employee>()
            .Interceptors(InterceptorReference.ForType<MyInterceptor>())
            .SelectedWith(new DerivedClassMethodsInterceptorSelector()).Anywhere);
        container.Register(Classes.FromAssembly(Assembly.GetExecutingAssembly()).Pick().WithService.FirstInterface());

        var employee = container.Resolve<Employee>();
        Person.PersonBaseMethodHitCount = 0;
        Person.PersonSomeMethodToBeOverriddenHitCount = 0;
        Employee.EmployeeCannotInterceptHitCount = 0;
        Employee.EmployeeSomeMethodToBeOverriddenHitCount = 0;
        MyInterceptor.HitCount = 0;
        employee.BaseMethod();
        Assert.That(Person.PersonBaseMethodHitCount, Is.EqualTo(1));
        // The BaseMethod was not overridden in the derived class so the interceptor should not have been called.
        Assert.That(MyInterceptor.HitCount, Is.EqualTo(0));

        Person.PersonBaseMethodHitCount = 0;
        Person.PersonSomeMethodToBeOverriddenHitCount = 0;
        Employee.EmployeeCannotInterceptHitCount = 0;
        Employee.EmployeeSomeMethodToBeOverriddenHitCount = 0;
        MyInterceptor.HitCount = 0;
        employee.SomeMethodToBeOverridden();
        Assert.That(Person.PersonSomeMethodToBeOverriddenHitCount, Is.EqualTo(0));
        Assert.That(Employee.EmployeeSomeMethodToBeOverriddenHitCount, Is.EqualTo(1));
        Assert.That(MyInterceptor.HitCount, Is.EqualTo(1)); //The test errors out on this line

        Person.PersonBaseMethodHitCount = 0;
        Person.PersonSomeMethodToBeOverriddenHitCount = 0;
        Employee.EmployeeCannotInterceptHitCount = 0;
        Employee.EmployeeSomeMethodToBeOverriddenHitCount = 0;
        MyInterceptor.HitCount = 0;
        employee.CannotIntercept();
        Assert.That(Employee.EmployeeCannotInterceptHitCount, Is.EqualTo(1));
        Assert.That(MyInterceptor.HitCount, Is.EqualTo(0));

テストが失敗した場所を示すコメントを追加しました。

DerivedClassMethodsInterceptorSelector で問題が発生していることがわかります。

セレクタ:

public class DerivedClassMethodsInterceptorSelector : IInterceptorSelector
{
    public IInterceptor[] SelectInterceptors(Type type, MethodInfo method, IInterceptor[] interceptors)
    {
        return method.DeclaringType != type ? new IInterceptor[0] : interceptors;
    }
}

型の比較を行う場合、型変数は System.RuntimeType ですが、Employee にする必要があります (少なくともこれは私の理解です)。

編集: この問題は、Castle.Windsor および Castle.Core 3.2.1 を使用して発生していました。NuGet に 3.1.0 パッケージをインストールすると、コードは期待どおりに動作します。

私はこれがバグであることに傾いていますが、単にロジックが変更されている可能性もあります。

4

1 に答える 1

1

この単純な単体テストで、バージョン 3.3.3 で同じ問題を再現できました。

[TestClass]
public class MyUnitTest
{
    [TestMethod]
    public void BasicCase()
    {

        var ProxyFactory = new ProxyGenerator();
        var aopFilters = new IInterceptor[] {new TracingInterceptor()};
        var ConcreteType = typeof(MyChild);

        var options = new ProxyGenerationOptions { Selector = new AopSelector() };

        var proxy = ProxyFactory.CreateClassProxy(ConcreteType, options, aopFilters) as MyChild;
        proxy.DoIt();

    }
}

public class AopSelector : IInterceptorSelector
{
    public IInterceptor[] SelectInterceptors(Type runtimeType, MethodInfo method, IInterceptor[] interceptors)
    {
        Assert.IsTrue(runtimeType == typeof(MyChild));

        return interceptors;
    }
}

public class MyWay
{
    public virtual void DoIt()
    {
        Thread.Sleep(200);
    }
}
public class MyChild : MyWay
{
    public virtual void DoIt2()
    {
        Thread.Sleep(200);
    }
}

public class TracingInterceptor : IInterceptor
{
    public void Intercept(IInvocation invocation)
    {
        var isProperty = invocation.Method.Name.StartsWith("get_")
                      || invocation.Method.Name.StartsWith("set_");

        if (isProperty)
        {
            invocation.Proceed();
            return;
        }

        LogMethod(invocation);
    }

    protected virtual void LogMethod(IInvocation invocation)
    {
        var target = (invocation.InvocationTarget ?? invocation.Proxy).GetType().Name;
        var stopwatch = Stopwatch.StartNew();

        try
        {
            stopwatch.Start();
            invocation.Proceed();
        }
        finally
        {
            stopwatch.Stop();
            var result = stopwatch.ElapsedMilliseconds;
        }
    }
}

TypeUtil.GetTypeOrNullCastle のソース コードと編集方法を次のように変更して修正しました。

public static Type GetTypeOrNull(object target)
{
    if (target == null)
    {
        return null;
    }

    var type = target as Type;
    if (type != null)
    {
        return type;
    }

    return target.GetType();
}

もちろん、これは単純な修正です。問題は別の場所にあり、このメソッドに渡されたオブジェクト インスタンスではなく、そのインスタンスが渡されているためですType。その上で動作します。TypeGetType

于 2015-01-06T10:23:02.000 に答える