CreateHandler Has No Implementation

Topics: Logging Application Block, Policy Injection Application Block
Aug 17, 2012 at 5:11 AM

First of all, I am creating a dll which uses the Enterprise Libraries. The dll cannot have any external dependencies. Therefore, I am combining my dll with other dlls using ILMerge.

When my dll got loaded it blew up saying it could not find the Unity library. So I added Microsoft.Practices.Unity.dll. However, now I am getting the error

Unhandled Exception: System.TypeLoadException: Method 'CreateHandler' in type 'Microsoft.Practices.EnterpriseLibrary.Logging.PolicyInjection.LogCallHandlerAttribute' from assembly '..., Version=1.0.0.0, Culture=neutral, PublicKeyToken=...' does not have an implementation.

I don't know why this is happening or why Unity.dll is required in the first place. Any input is appreciated. Btw, I am just using the logging block with email as the sink and using the fluid interface. For that I have references to M..P..EnterpriseLibrary.Common, M..P..EnterpriseLibrary.Data, M..P..EnterpriseLibrary.logging and M..P..ServiceLocation (and the Unity).

Aug 17, 2012 at 5:32 AM

If you are just using Logging with an EmailTraceListener then you shouldn't need a reference to Microsoft.Practicies.EnterpriseLibrary.Data.dll.  

You should merge the following assemblies:

Microsoft.Practices.EnterpriseLibrary.Common.dll
Microsoft.Practices.EnterpriseLibrary.Logging.dll
Microsoft.Practices.ServiceLocation.dll
Microsoft.Practices.Unity.dll
Microsoft.Practices.Unity.Configuration.dll
Microsoft.Practices.Unity.Interception.dll
Microsoft.Practices.Unity.Interception.Configuration.dll

I think you are hitting the error because the HandlerAttribute is defined in the assembly Microsoft.Practices.Unity.Interception.dll.

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com 

Aug 17, 2012 at 5:34 AM

Also, if you are interested see this answer at Stack Overflow for an approach to embed assemblies as resources with a custom resolver:

http://stackoverflow.com/questions/8964640/ilmerge-enterprise-libary-5-0

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com 

Aug 17, 2012 at 6:39 AM

Thanks a lot, your first post solved the initial issue. Now during the execution I get the exception System.TypeLoadException: Inheritance security rules violated by type M..P..EnterpriseLibrary.Common.Instrumentation.CommonWmiInstaller. Derived types must either match the security accessibility of the base type or be less accessible.

It's not the same error but similar (security) as what was writen at the link in your second post. So I guess I should give up on ILMerge. The issue is that I have a lot of dlls where I have to make that change so I wanted to get some clarification/input first. Please consider that my 'application' is a dll/plugin (plugin.dll) which uses the another dll (log.dll) and that dll (log.dll) uses the enterprise library. So for log.dll I would add the EntLib dlls as "embedded resource" and add the resolve handler in the constructor of the class in log.dll, correct?

I believe the dependent dlls will be loaded before any code is being executed in my log.dll. That means the handler to resolve the missing dll never gets installed and therefore can't resolve/load the dll. How how can I manually load that dll?

Aug 17, 2012 at 10:03 PM

This thread, http://entlib.codeplex.com/discussions/363098, shows an example for the assembly resolver but loading from disk and not a resource.

I would add the AssemblyResolve event in the Log static constructor.  But it might not work if you have instance or static (Enterprise Library type) variables in your Log class (depends on the implementation).  In that case you could create a new class that just performs the initialization with the requirement for API users to initialize that before any use of the API.  e.g. LogInitializer.Initialize();  Or another way of saying something very similar is to change the design to avoid Enterprise Library references and defer their loading until later; A facade of sorts.

Another alternative might be a custom build of Enterprise Library where you can tweak the code to work better with ILMerge.

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com 

Aug 18, 2012 at 10:21 PM

I tried many things to get this done with the AppDomain including separate initializer class etc. However, the line AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); always blows up. The line AppDomain a = AppDomain.CurrentDomain; does not cause any issues so it seems it does not like adding a handler. I am not sure why, though.

In addition, I am being told that in case of Dynamics CRM this is not a good approach. If I understand it correctly, the handler would be added to some engine (the AppDomain) that manages plugins (including the one I try to create which uses my logging library based on the Enterprise Library). That part is unsupported and maybe that's the reason it blows up. Let's assume the handler could be added. The issue is that my plugin must be registered (using some tool). So if I reregister the plugin there might still be a handler in place for the old plugin (which now was replaced be registering a new one). At least this is how I understand it.

So I am kind of lost. The ILMerge does not seem to work due to security issues, etc and loading the dlls from resources does not work as I can't install the handler. Is there any other suggestion or are you aware of anybody who has used Enterprise Libraries in combination with Microsoft Dynamics CRM Online (which is more restrictive as I don't have access to the file system, GAC, etc).

Aug 19, 2012 at 2:45 AM

How does it blow up?  What exception do you get?

I'm just curious if this environment is standard Microsoft Dynamics CRM or a result of policies and standards of the specific implementation you are working with?  It seems quite restrictive based on your previous postings as well.

I was thinking that you could try to just brute force register the binary data but I think you will run into load context issues.

The only idea I can think of is to create your own app domain and load all of your assemblies in that app domain and Executing Code in Another AppDomain.  Not sure if it will work based on your other input, though.

--
Randy Levy
Enterprise Library support engineer
entlib.support@live.com 

 

 

Aug 24, 2012 at 7:23 AM

Randy, the exception says "Unexpected exception from plug-in (Execute): xxx: System.TypeInitializationException: The type initializer for 'xxx' threw an exception. There is no inner exception.

The environment is hosted by Microsoft (or somebody they contract). It is indeed very restrictive. The SDK includes a tool to upload the plugins and register events that trigger the plugin. This tool does not allow you to upload just any binary. Maybe there is some unsupported way around the tool but I suspect they do their best to block that.

Btw, I did back track and remove piece after piece until finally I removed everything from the Enterprise Library. There was no reference, no ILMerge or anything. Yet I still did get a security error for Microsft.Practices....CommonWmiInstaller. I was told by somebody else that adding an event handler is not supported and I would have to handle the unregistration of the dll. Based on that I suspect that at least one of my many trials was successful in adding a handler but that it was not removed when I registerd a new version of the dll. That could also explain the fact that sometimes I got one error and another time a different one despite not having changed any code, nor uploaded any other plugin but simple triggered the plugin through the app several times. I finally created a new trial account, took that very same dll (that had no Enterprise related code), registered it and there was no Enterprise related error (CommonWmiInstaller) anymore.

Anyways, I have given up on using the Enterprise Libraries with Dynamics CRM Online. I started writting my own logging library.