11

I'm working on a utility for SharePoint. It's an app that works for both SharePoint 2007 and 2010. When I have a reference to the 12.0.0.0 version of the SharePoint.dll, the app works for SharePoint 2007, but not for 2010. If I reference version 14.0.0.0 of the dll, then the app works great for 2010, but not for 2007.

I can easily tell which .dll that I need to use by looking on the file system with the following code, checking for 12 in the path (SharePoint 2007) or 14 (SharePoint 2010).

System.IO.File.Exists(
                    Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFiles) + 
                    @"\Microsoft Shared\web server extensions\14\ISAPI\Microsoft.SharePoint.dll"));

When developing, I make the reference in Visual Studio, so it builds either for 2007 or 2010. I want to be able to release the app where it works on BOTH version of SharePoint. So, I need some way to load/use whatever .dll makes sense for the user running the app.

How do I dynamically choose and load a .dll at runtime?

Ryan Hayes
  • 5,290
  • 4
  • 42
  • 52

5 Answers5

16

Reflection? Dependency Injection? You are making life hard for yourself!

Compile against Microsoft.SharePoint.dll v12 and it will work on 2007.

Deploy to 2010 and it will 'just work' (in nearly all cases) as SharePoint 2010 already has binding redirects setup so any reference to v12 will be redirected to v14.

You don't need to do anything configuration wise.

The only situations where you need to get more complex than this are

  • Instances where something would work on 2007 but not on 2010 (I can't think of anything to hand).

  • Where you may want to make use of 2010 specific features.

If this is the case then what I, personally, would do is to dual compile. Modify the .csproj file to produce 2 slightly different versions, use a parameter and conditional compilation (just like you would with #if DEBUG) for product specific versions of code where necessary (there will be very few of these). You can also use these conditions in the references in .csproj e.g.

 <Reference Include="Microsoft.SharePoint">
    <HintPath Condition="'$(SP2010)'!='true'">PathToV12\Microsoft.SharePoint.dll</HintPath>
    <HintPath Condition="'$(SP2010)'=='true'">PathToV14\Microsoft.SharePoint.dll</HintPath>        
 </Reference>

Disadvantages

  • You end up with 2 versions of your program

Advantages

  • You end up with 2 versions of your program! Many of the changes you might want to make in the 2010 version would be in manifet.xml, feature.xml and the other config files - reflection, dependancy injection etc isn't going to do anything for you here.
  • Still have a single version of source code (with minor conditional compilation)
  • Compiler will pick up more errors (it can't for example figure out at compile time that that funky thing you are doing with Reflection to call a new method in v14 will actually work)
Ryan
  • 23,871
  • 24
  • 86
  • 132
4

You need to use reflection. Have a look at Assembly.LoadFile and Assembly.Load.

If you need to work with class methods in it you can use it like this :

        Assembly u = Assembly.LoadFile(path);
        Type t = u.GetType(class title);
        if (t != null)
        {
            MethodInfo m = t.GetMethod(method);
            if (m != null)
            {
                if (parameters.Length >= 1)
                {
                    object[] myparam = new object[1];
                    myparam[0] = ......;
                    return (string)m.Invoke(null, myparam);
                }
                else
                {
                    return (string)m.Invoke(null, null);
                }
            }
        }
        else
        {
             // throw exception. type not found
        }
Incognito
  • 16,567
  • 9
  • 52
  • 74
3

By way of AppDomain.AssemblyResolve, you can check for the existence of the DLL and return whichever one is present:

AppDomain.AssemblyResolve += delegate(object sender, ResolveEventArgs e)
{
    if (e.Name == "Microsoft.SharePoint")
    {
        // do your check here and return the appropriate Assembly
        // or maybe just skip an explicit check and instead return either
        // Assembly.Load("Microsoft.SharePoint, Version=14.0.0.0") or
        // Assembly.Load("Microsoft.SharePoint, Version=12.0.0.0"), whichever works first
        // but beware of recursion!
    }
};

An assembly binding redirect won't work for you in this case because that is static in your config file and you want this to dynamically work on any machine with either SP2007 or SP2010.

Kent Boogaart
  • 175,602
  • 35
  • 392
  • 393
  • +1 - i had to deal with this in the past and this is what I did. – James Manning Aug 15 '10 at 20:59
  • You don't need to do this - see my answer. Binding redirects are already in place in SharePoint 2010 to redirect v12 to v14 so it will just 'automagically' and dynamically work. Oh - and 2007 redirects 2003 (v11) to v12 too. – Ryan Aug 16 '10 at 13:14
2

I think you need to look at assembly binding redirection in the framework.

http://msdn.microsoft.com/en-us/library/2fc472t2.aspx

You can use the '.net framework configuration tool' to configure the redirection.

SoftwareGeek
  • 15,234
  • 19
  • 61
  • 78
  • A binding redirect is configuration, which is not dynamic. – Kent Boogaart Aug 15 '10 at 18:58
  • @Kent Boogaart - yes, but since he knows what assemblies to load, these can be configured right ? – SoftwareGeek Aug 15 '10 at 19:08
  • Only if he wants to selectively configure the app for every machine to which he's deploying, which he states he does not. He wants to deploy once and have it work regardless of the version of SP installed. – Kent Boogaart Aug 15 '10 at 21:53
  • I could have the user select on the first load which version of SharePoint the app is being used for, and then configure and restart the app. – Ryan Hayes Aug 15 '10 at 23:13
  • @Ryan: that assumes your app has permission to write to the config file, which it generally wouldn't (or shouldn't) once installed. – Kent Boogaart Aug 16 '10 at 07:02
  • You don't need to set these binding redirects up - they are already in place. – Ryan Aug 16 '10 at 13:12
-2

This sounds like a great case for Dependency Injection using one of the DI frameworks like Unity or Castle Windsor. There are others out there, but I'm already risking a religious war simply by mentioning these two. :)

Robaticus
  • 22,857
  • 5
  • 54
  • 63