Pracuję nad uaktualnieniem naszego projektu z .Net 2 do .Net4.5, jednocześnie przesyłam tyle referencji, ile Mogę do NuGet i upewnić się, że wersje są aktualne.Używanie Castle.Windsor do zarejestrowania przechwytywacza tylko dla klasy pochodnej, a nie dla klasy bazowej
mam problemu z jedną z prób uruchomienia
klasach Test:
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();
}
}
Test (nie ma konfiguracji dla tego urządzenia):
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));
Dodałem komentarz, aby wskazać, gdzie test się nie powiedzie.
O ile mogę powiedzieć problem powstaje w DerivedClassMethodsInterceptorSelector
Selector:
public class DerivedClassMethodsInterceptorSelector : IInterceptorSelector
{
public IInterceptor[] SelectInterceptors(Type type, MethodInfo method, IInterceptor[] interceptors)
{
return method.DeclaringType != type ? new IInterceptor[0] : interceptors;
}
}
Kiedy to sprawia, że porównanie typów, zmienna typu jest System.RuntimeType ale powinny być Employee (przynajmniej to jest moje zrozumienie).
EDIT: Ten problem został występujących przy użyciu Castle.Windsor i Castle.Core 3.2.1 Po dokonaniu Nuget zainstalować pakiet 3.1.0 kod działa zgodnie z oczekiwaniami.
Jestem skłonny do tego, że to błąd, ale mógłbym też zmienić logikę.
Powieliłem to dokładne zachowanie. –
Jakie serwery proxy są używane? Jeśli jest używany? Pracuję z Windsor 3 lata temu, ale jak pamiętam, większość takich problemów dotyczyła dynamicznych serwerów proxy (windsor + proxy + nhibernate czasami powodują uszkodzenie mózgu). Najlepszym sposobem jest zbadanie System.RuntimeType w debuggerze bardziej bliższym - to przodkowie, atrybuty, a nawet nazwa może dać ci informacje do podjęcia decyzji. –
Jedyne proxy, które są używane, to te, które Windsor tworzy automatycznie podczas rejestracji z przechwytującymi, podczas debugowania jest absolutnie żadnych informacji na temat System.RuntimeType. Po krótkim wyglądzie źródła GetType jest wywoływany na obiekcie docelowym przed wywołaniem selektora przechwytywania iw tym przypadku okazuje się, że obiekt docelowy był już obiektem typu. – Phaeze