In today’s design session, we called for a quick and dirty hack before we can put a strategic solution in place. The hack is to extract the original target from a proxy of said target.
Given an instance of ITestObject, it is expected to be either of type TestObject or a proxy around an instance of TestObject. Either way, we want to get hold of the TestObject. After digging around the Spring.Net’s source code, we found it is possible. Below is the code to achieve this.
/// <summary>
/// Extract and return the proxy target if <paramref name="o"/> is a
/// proxy generated by <see cref="ProxyFactory"/>. Otherwise, return
/// <paramref name="o"/> itself.
/// </summary>
/// <typeparam name="T">The expected type of the target object.</typeparam>
/// <param name="o">
/// An instance of <typeparamref name="T"/> or a proxy of it.
/// </param>
/// <returns>
/// The target instance of <paramref name="o"/> if it is a proxy.
/// Otherwise, <paramref name="o"/> itself.
/// </returns>
/// <exception cref="InvalidCastException">
/// If <paramref name="o"/> is neither an instance of <typeparamref name="T"/>,
/// nor a proxy of <typeparamref name="T"/> instance.
/// </exception>
private static T ExtractTarget<T>(object o)
{
AdvisedProxy ap = o as AdvisedProxy;
return (T)(ap == null ? o : ap.m_targetSourceWrapper.GetTarget());
}
Bear in mind that this make your code depends on the detail implementation of the Spring.Net ProxyFactory class, which may be changed in future Spring.Net releases. Hence use it with caution.
Here is the test case for ExtractTarget method.
private static T CreateProxy<T>(T target)
{
ProxyFactory pf = new ProxyFactory(target);
pf.AddInterface(typeof(T));
return (T) pf.GetProxy();
}
[Test] public void ProxyTargetTest()
{
ITestObject target = new TestObject();
Assert.AreSame(target, ExtractTarget<TestObject>(target));
ITestObject proxy = CreateProxy<ITestObject>(target);
Assert.AreSame(target, ExtractTarget<TestObject>(proxy));
}
No comments:
Post a Comment