program to interface… in sharepoint

[Update]  

I’ve posted a workaround to this issue here: https://blogs.msdn.com/erwinvandervalk/archive/2009/06/08/using-interfaces-and-base-classes-in-different-assembly-using-vsewss-1-3.aspx .  

[Original post] 

One of the common practices I try to follow is: Program to interface, not implementation.

It allows you to decouple components from each other and easily plug in different implementation. This is great for test driven development, where you can replace all the dependencies of the object under test with Mock objects.

But when I tried to do something similar in our Sharepoint Guidance project, I ran into a problem with the Visual Studio Extensions for Windows Sharepoint Services (VSSeWSS) 1.3.

The problem

I had created two assemblies, one with an interface definition and the other with the actual implementation. Seems pretty basic, but when I tried to use it to create a WSP package, I got the following error:

Error    1    VSeWSS Service Error: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.

Log file written to: C:\Windows\system32\config\systemprofile\AppData\Roaming\Microsoft\VSeWSS 1.3\VSeWSS1.3 service.log        0    0   

Ok, maybe the log file explains what’s wrong?

2009/04/10 11:13:59    Error System.Reflection.ReflectionTypeLoadException: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information.    at System.Reflection.Module._GetTypesInternal(StackCrawlMark& stackMark)    at System.Reflection.Module.GetTypes()    at Microsoft.SharePoint.Tools.Reflection.ModuleWrapper.GetTypes()    at Microsoft.SharePoint.Tools.Reflection.TypeFinder.GetTypesAsType(IAssemblyWrapper assembly, ITypeWrapper targetType)    at Microsoft.SharePoint.Tools.Reflection.TypeFinder.Find(IAssemblyWrapper assembly, ITypeWrapper targetType)    at Microsoft.SharePoint.Tools.SharePointProxies.WSPViewFacade.CreateWebPartReferenceResolverClassMap(String[] paths)    at VSeWSS.Server.Services.SPService.CreateWebPartReferenceResolverClassMap(String[] paths)

How incredibly useful.

The solution

After a lot of puzzling, I found out that the VSSeWSS 1.3 tool has problems with separating the implementation and interfaces in seperate DLL’s. Even if you reference the DLL’s, but not add project references, it gives the previous error message when packaging it.

However, i found if you set ‘copy local’ to False in the assembly references, the problem goes away. Of course, it does create another problem. How do you get the dll’s on sharepoint.

The solution I’m going to take is: Create a feature that puts the DLL’s on the server. Create another feature that wants to use the dll’s, but has ‘copy local’ to false. I know, it’s not pretty, but it works.

Hope this helps,

_Erwin

Comments

  • Anonymous
    April 10, 2009
    Wouldn't it be easier to have implementation and interface in one assembly? The reason to separate them into multiple assemblies would be if there are two completely different features that are not in the same assembly but you still want to share the same interface. Then I would question whether they should really share the same interface if they are so different. The principle that says "program to interface" says nothing about separating the binaries. David.

  • Anonymous
    April 13, 2009
    Hi David, Thanks for your reply. You are right, the principle program to interface does not demand seperating the binaries. As a believer in the YAGNI principle, i would only seperate the implementation from the interface if I have a need for it. For example, if you use interfaces as a way to achieve polymorfism, you don't need to seperate out the binaries. However, if you want to achieve a higher level of decoupling, you want to be able to seperate out the interface. For example, I wanted to build two logging implementations that I can plug in. One that was as simple as possible and the other based on enterprise library. In this case, keeping the interface in a different assembly does make a lot of sense. So my point was that with the VSSeWSS was that I COULDN'T put the interfaces in a different assembly, not that you MUST put them in an other assembly :) _Erwin