COMPlusExceptionCode -532462766 in Validation Application Block Windows Service

Topics: Validation Application Block
May 3, 2011 at 10:54 PM

I am getting an InvalidOperationException that says "The type ValidatorFactory cannot be constructed. You must configure the container to supply this value." This is accompanied by the COMPlusExceptionCode listed in the title of this post.

I am running Entlib 5.0 with Unity 2.0 on a Windows Server 2003 R2 / .Net Framework 4.0 and have invoked the same code through a Console program as well as through a Windows Service. The error does not present when invoking through a Console program. My assemblies are not deployed in GAC. They come from either the Entlib 5.0 or Unity 2.0 installs. I have confirmed that by looking at the path displayed in  Visual Studio (Add References... -> .Net Tab -> look for Enterprise Library Validation Application Block). That said, I did try the typeRegistrationProvidersConfiguration nonetheless and it didn't make any difference.

My code does not use config files for unity / entlib setups. I am using Attribute Based validation on method arguments and use [ValidationComposition(CompositionType.And)]. Here is how my unity container is setup

        private static void Main()

        {
            using(IUnityContainer container=new UnityContainer())
            {
                container
                    .AddNewExtension<Interception>()
                    .RegisterType<MyWindowsService>
                    (
                        new ContainerControlledLifetimeManager(),
                        new Interceptor<VirtualMethodInterceptor>("MyVMInterceptor"),
                        new InterceptionBehavior<PolicyInjectionBehavior>()
                     )
                    .Configure<Interception>()
                    .AddPolicy("MethodValidation")
                    .AddMatchingRule(typeof(TagAttributeMatchingRule), new InjectionConstructor("MethodToValidate"))
                    .AddCallHandler
                         (typeof(SomeCustomCallHandler),
                          "SCCHandler",
                          new ContainerControlledLifetimeManager(),
                          new InjectionProperty("Field1", "from"),
                          new InjectionProperty("Field2", "to")
                          )
                    .AddCallHandler
                        (typeof(ValidationCallHandler), 
                        "VHandler", 
                        new ContainerControlledLifetimeManager(),
                        new InjectionConstructor
                            ("RuleSet",
                            SpecificationSource.Attributes
                            )
			);
                EnterpriseLibraryContainer.Current = new UnityServiceLocator(container);
                ServiceBase.Run(container.Resolve<MyWindowsService>());


Here is how my intercepted method is setup:
        [Tag("MethodToValidate")]
        public virtual bool MyMethod
            (
                [ValidatorComposition(CompositionType.And)]
                [StringLengthValidator(1,11)]
                [NotNullValidator]
                string arg_1,
                [ValidatorComposition(CompositionType.And)]
                [StringLengthValidator(1,11)]
                [NotNullValidator]
                string arg_2,
                [ValidatorComposition(CompositionType.And)]
                [StringLengthValidator(1, 160)]
                [NotNullValidator]
                string arg_3
            )
        {
            bool success = false;
            //Some method processing
                success = true;
            return success;
        }

The virtual method interception part seems to be working fine since my first CallHandler executes without any problems; I also see a clean handler transition to 
Validation Call Handler. However, when the ValidationCallHandler kicks in, the code gives an error when attempting to resolve ValidatorFactory. The error does not give
out a good stack trace, but stepping through code shows that the failure happens when ValidationHandler class attempts to invoke CreateValidator(inputParameter) in its
Invoke() method. This method in turn calls ParameterValidatorFactory.CreateValidator(parameter).

This function in turn calls compositeBuilder.AddValueValidator() for each ValidatorDescriptor found:
                compositeBuilder.AddValueValidator(
                    descriptor.CreateValidator(
                        paramInfo.ParameterType,
                        null,
                        null,
                        ValidationFactory.DefaultCompositeValidatorFactory));
Inside this function, the call to ValidationFactory.DefaultCompositeValidatorFactory fails as it attempts to resolve the default validation factory from the container:
        public static ValidatorFactory DefaultCompositeValidatorFactory
        {
            get { return EnterpriseLibraryContainer.Current.GetInstance<ValidatorFactory>(); }
        }

So does it mean the registration did not happen correctly and so the container could not find the ValidatorFactory? The actual error happens somewhere down the line
when attempting to execute strategy / build up as part of Resolve serviceType.

Any pointers for me please?

May 4, 2011 at 2:33 AM

Here is some additional information. Looks like the actual failure happens in a call to GuardTypeIsNonPrimitive() in DynamicMethodConstructorStrategy.PreBuildUp() function. It seems for some Type associated with

ValidationFactory the function ConstructorSelectorPolicyBase.SelectConstructor() returns a null ctor (FindInjectionConstructor(TypeToConstruct) and FindLongestConstructor(TypeToConstruct) both return a null). As a result

GuardTypeIsNonPrimitive() throws the InvalidOperationException as detailed above.

According to this post this problem happens in Unity 2.0 because the Resolver is expecting a public constructor. In this case, I have confirmed that my method as well as my windows service does have a public access

qualifier. Other than these classes, I really don't have any other classes written for Validation Call Handler.

May 4, 2011 at 9:24 AM

Hi,

I've seen this is somehow related to you other post (http://entlib.codeplex.com/discussions/253435). Is my understanding correct that this works fine with Console App but NOT with Windows Service? While we're still investigating and trying to reproduce your problem, would it be feasible if you can provide us a small simple repro project to help us with our investigation. Thanks.

Gino Terrado
Global Technologies and Solutions
Avanade, Inc.
entlib.support@avanade.com

 

 

May 4, 2011 at 7:21 PM

It may or may not be related to VirtualMethodInterceptor, but I guess the two are related in that they are part of the same solution. Your understanding is correct: it works for Console App but not for Windows Service. Actually what might help me make progress is some guidance on this other post (http://unity.codeplex.com/discussions/256227). In the meantime, I will put together a repro project and send over.

May 4, 2011 at 10:05 PM

I think I found the offending line, but need help to figure out the right way of writing that line (not doing it is not an option). I am using ServiceLocator to reference the current container since my code is split across multiple projects and each object needs some way of referencing the container in order to resolve objects / classes it wants to use. I think ServiceLocator pattern is a good way of achieving that as I don't need to keep a handle on the container with every object that needs it.

So, this line in my Main() is supposed to set my current container:

 

EnterpriseLibraryContainer.Current = new UnityServiceLocator(container);

 

With the current container set as above, now I can reference it from any other project, for instance:

 

EnterpriseLibrary.Current.Resolve<MyWindowsService>()

This works great for the most part except for Validation. In the validation process, ValidationFactory.DefaultCompositeValidatorFactory tries to resolve the ValidationFactory using the current container thus:

 

        public static ValidatorFactory DefaultCompositeValidatorFactory
        {
            get { return EnterpriseLibraryContainer.Current.GetInstance<ValidatorFactory>(); }
        }

 

Which ultimately leads to an error. Once I inserted this line in the console program, I started getting error there as well.

In the case of Windows Service the error returned is an InvalidOperationException. In case of Console program I get ActivationException, but ultimately the root cause is the same InvalidOperationException which is due to a null ctor returned for ValidatorFactory (which I detailed in the second post I made on this thread).

My hypothesis at this point is that by explicitly setting EnterpriseLibraryContainer.Current property I am probably losing reference to the original value of EnterpriseLibraryContainer.Current (perhaps set by the framework even before it started taking an Registration requests from my application?), which would have resolved the ValidatorFactory reference correctly. Not setting the property explicitly does not work either: I get InvalidOperationException if I try to use that property without explicitly setting it. My only other option is to maintain a Container property in each class that could potentially use a current container reference (potentially every major public class), which would be set through InjectionParameters. I don't prefer that route but would take it if that is the only work around available.

So, could you tell me what is the right way of initializing EnterpriseLibraryContainer.Current? Also, why should this property be required to be set explicitly? Shouldn't the framework set this internally (perhaps as readonly), especially since it uses EnterpriseLibraryContainer.Current extensively to resolve objects? Application programs should be allowed to grab it, where needed, but not change it.

 

 

May 6, 2011 at 12:03 AM

Even if you're not using the configuration file, you still need to add the EnterpriseLibraryCoreExtension to the container. Without it none of the type registrations are set up correctly, and it won't know how to resolve the ValidationFactory (or a bunch of other stuff).

When you set up your container, call container.AddNewExtension<EnterpriseLibraryCoreExtension>() (this will also automatically pull in the interception extension) and it should do the trick.

 

May 6, 2011 at 6:37 AM

Thanks a lot for the help. That did work. So if I understand correctly, if you are not using ServiceLocator, then use AddNewExtension<Interception>(). If you are using ServiceLocator, then use AddNewExtension<EnterpriseLibraryCoreExtension>(). Correct?