Unity 3.5 changed InstanceIsAssignable leads to problems

Jul 2, 2014 at 8:51 PM
Hi all,

In our MVC project we used some cashing of requests to external service with the help of unity

in global.asax.cs
            _serviceProxy = new ServiceProxy<IWcfServer>(CommonHelper.AppSetting("WCFURL"));
            _wcf = (IWcfServer)_serviceProxy.GetTransparentProxy();
            container.RegisterInstance(_wcf, new ContainerControlledLifetimeManager());
calls to methods of the _wcf are intercepted and are redirected to the method
in public sealed class ServiceProxy<T> : BaseRealProxy<T>
        protected override object InvokeChannel(MethodBase methodBase, Dictionary<string, object> members, Type returnType)
        {
 /// return result
        }
so in 3.0 it worked basically call to _wcf.GetData() was intercepted, cache was checked, etc.
but in 3.5 Guard.cs was changed:
it was
public static void InstanceIsAssignable(Type assignmentTargetType, object assignmentInstance, string argumentName)
        {
///...
            if (!assignmentTargetType.IsInstanceOfType(assignmentInstance))
            {
                throw new ArgumentException(string.Format(CultureInfo.CurrentCulture, Resources.TypesAreNotAssignable, new object[]
                {
                    assignmentTargetType,
                    Guard.GetTypeName(assignmentInstance)
                }), argumentName);
            }
        }
and it became
        public static void InstanceIsAssignable(Type assignmentTargetType, object assignmentInstance, string argumentName)
        {
///...
            if (!IntrospectionExtensions.GetTypeInfo(assignmentTargetType).IsAssignableFrom(IntrospectionExtensions.GetTypeInfo(assignmentInstance.GetType())))
            {
                throw new ArgumentException(string.Format(CultureInfo.get_CurrentCulture(), Resources.TypesAreNotAssignable, new object[]
                {
                    assignmentTargetType,
                    Guard.GetTypeName(assignmentInstance)
                }), argumentName);
            }
        }
and here lies the problem. because suddenly we realized that call to GetType is also intercepted and redirected to our proxy...

So the GetType is handled by our protected override object InvokeChannel(MethodBase methodBase, Dictionary<string, object> members, Type returnType) method therefor InstanceIsAssignable fails.
Adding such a code
if (methodBase.Name == "GetType") return this.GetType();
won't help because the GetType call again will be intercepted...
How shall I use RegisterInstance so the call to GetType won't be intercepted?
Jul 6, 2014 at 7:30 PM
I'm not sure I follow 100% where and how you are using interception and what exact types you are dealing with. However, what you post appears similar to this issue: container.RegisterInstance failed for COM interfaces.

The Guard.cs code you posted is different then the latest Unity version implementation:
        public static void InstanceIsAssignable(Type assignmentTargetType, object assignmentInstance, string argumentName)
        {
            if (assignmentTargetType == null)
            {
                throw new ArgumentNullException("assignmentTargetType");
            }

            if (assignmentInstance == null)
            {
                throw new ArgumentNullException("assignmentInstance");
            }

            if (!assignmentTargetType.GetTypeInfo().IsAssignableFrom(assignmentInstance.GetType().GetTypeInfo()))
            {
                throw new ArgumentException(
                    string.Format(
                        CultureInfo.CurrentCulture,
                        Resources.TypesAreNotAssignable,
                        assignmentTargetType,
                        GetTypeName(assignmentInstance)),
                    argumentName);
            }
        }
However, it looks equivalent so I don't think will make a difference in behavior.

Here are some options (I'm not saying they are great options):
  • Continue Using Unity 3.0
  • Modify Unity 3.5 source to do what you want
  • If you can register a concrete type without a mapping (pretty sure that doesn't work for you) you could bypass the check
  • Move some of the "logic" out of Unity into a factory to avoid the Guard check. The factory could use Unity to resolve the appropriate objects.
I'm curious if you have an idea of what a new implementation of InstanceIsAssignable using TypeInfo should be?

~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to