Designed not to work on Forms?

Topics: Policy Injection Application Block
Apr 13, 2007 at 8:23 PM
Maybe I'm totally dense, but this doesn't seem to work with Forms.
If I have the following:
public interface IMyForm
        void Magic();
    public class MyForm : Form, IMyForm {
        FlowLayoutPanel flowPanel;
        public MyForm()
            flowPanel = new FlowLayoutPanel();
        public void Magic()
            Label label = new Label();
            label.Text = "Magic";

Which I create with this line:
IMyForm magicForm = PolicyInjection.Create<MyForm, IMyForm>();

And I setup a Tag matching rule with some handler (Logging Handler in my case (purpose is to log form lifetime)), I get an exception:
System.Collections.Generic.KeyNotFoundException was unhandled
Message="The given key was not present in the dictionary."
at System.ThrowHelper.ThrowKeyNotFoundException()
at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
at Microsoft.Practices.EnterpriseLibrary.PolicyInjection.RemotingInterception.InterceptingRealProxy.AddHandlersForInterface(Type targetType, Type itf) in C:\EntLib3Src\App Blocks\Src\PolicyInjection\RemotingInterception\InterceptingRealProxy.cs:line 83
at Microsoft.Practices.EnterpriseLibrary.PolicyInjection.RemotingInterception.InterceptingRealProxy..ctor(Object target, Type classToProxy, PolicySet policies) in C:\EntLib3Src\App Blocks\Src\PolicyInjection\RemotingInterception\InterceptingRealProxy.cs:line 63
at Microsoft.Practices.EnterpriseLibrary.PolicyInjection.PolicyInjector.DoWrap(Object instance, Type typeToReturn, PolicySet policiesForThisType) in C:\EntLib3Src\App Blocks\Src\PolicyInjection\PolicyInjector.cs:line 203
at Microsoft.Practices.EnterpriseLibrary.PolicyInjection.PolicyInjector.Create(Type typeToCreate, Type typeToReturn, Object[] args) in C:\EntLib3Src\App Blocks\Src\PolicyInjection\PolicyInjector.cs:line 88
at Microsoft.Practices.EnterpriseLibrary.PolicyInjection.PolicyInjector.CreateTObject,TInterface(Object[] args) in C:\EntLib3Src\App Blocks\Src\PolicyInjection\PolicyInjector.cs:line 125
at Microsoft.Practices.EnterpriseLibrary.PolicyInjection.PolicyInjection.CreateTObject,TInterface(Object[] args) in C:\EntLib3Src\App Blocks\Src\PolicyInjection\PolicyInjection.cs:line 66
at PolicyInjectionQuickStart.MainForm..ctor() in C:\EntLib3Src\Quick Starts\PolicyInjection\CS\PolicyInjectionQuickStart\PolicyInjectionQuickStart\MainForm.cs:line 46
at PolicyInjectionQuickStart.Program.Main() in C:\EntLib3Src\Quick Starts\PolicyInjection\CS\PolicyInjectionQuickStart\PolicyInjectionQuickStart\Program.cs:line 28
at System.AppDomain.nExecuteAssembly(Assembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()

I guess this means I can't use PIAB with Forms... Is there an alternative (I really would love to get rid of explicitly placing the using(new Tracer("Audit")){...} code.
Apr 13, 2007 at 9:36 PM
Your usage certainly should work. While I'm debugging, could I ask you to try a couple of things?

First, what happens if you do Create<MyForm> instead of Create<MyForm, IMyForm>?

Also, have you tried:
MyForm form = new MyForm();
IMyForm magicForm = PolicyInjection.Wrap<IMyForm>(form);

and does it do anything different?

What happens if you put the TagAttribute on the class instead of the method?

And finally, do you have a small sample that reproduces the problem you could send me? (at <profilename>


Apr 13, 2007 at 10:19 PM
I've tried all Creates and Wraps with no success. I've also moved the TagAttribute with no success.
I will send you my test project.
Apr 13, 2007 at 11:38 PM
I have confirmed this is a bug. The proxy is hanging up on the unmanaged COM interfaces implemented by the base Form class. I'm working on a fix, but in the meantime you'll need to move the logic you want to intercept out to another class.
Apr 14, 2007 at 12:57 AM
The real fix is to change the AddHandlersForInterface method in the file InterceptingRealProxy.cs to:

        private void AddHandlersForInterface(Type targetType, Type itf)
            InterfaceMapping itfMapping = targetType.GetInterfaceMap(itf);
            int numMethods = itfMapping.InterfaceMethods.Length;
            for( int i = 0; i < numMethods; ++i)
                if (memberHandlers.ContainsKey(itfMapping.TargetMethods[i]))
                    memberHandlers[itfMapping.InterfaceMethods[i]] =

The only difference is the addition of the if check.
Apr 14, 2007 at 2:42 PM
This of course means I will have to compile the assemblies and sign them myself, are there any plans for distributing signed, patched assemblies in the pipeline?
Apr 16, 2007 at 7:02 PM

AB_dreeve wrote:
This of course means I will have to compile the assemblies and sign them myself, are there any plans for distributing signed, patched assemblies in the pipeline?

We're planning to release a patch version with refreshed binaries before too long, however we haven't worked out the details or the timing just yet. If you need the fix before that time, the best thing to do is update the code yourself rather than depend on the pre-signed binaries.