Выбирайте динамически во время выполнения, какую версию .dll следует использовать

Я работаю над утилитой для SharePoint. Это приложение, которое работает как для SharePoint 2007, так и для 2010 года. Когда у меня есть ссылка на версию SharePoint.dll 12.0.0.0, приложение работает в SharePoint 2007, но не в 2010 году. Если я ссылаюсь на версию 14.0.0.0 dll, то приложение отлично работает на 2010 год, но не на 2007 год.

Я могу с легкостью определить, какую DLL мне нужно использовать, просмотрев файловую систему со следующим кодом, проверяя 12 в пути (SharePoint 2007) или 14 (SharePoint 2010).

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

При разработке я делаю ссылку в Visual Studio, поэтому он создается либо в 2007, либо в 2010 году. Я хочу иметь возможность выпускать приложение, где оно работает в версии SharePoint BOTH. Итак, мне нужно каким-то образом загрузить/использовать любой .dll, который имеет смысл для пользователя, запускающего приложение.

Как я могу динамически выбирать и загружать DLL во время выполнения?

Ответ 1

Отражение? Внедрение зависимости? Вы делаете жизнь тяжело для себя!

Скомпилируйте файл Microsoft.SharePoint.dll v12 и он будет работать в 2007 году.

Разверните до 2010 года, и он будет "работать" (почти во всех случаях), поскольку SharePoint 2010 уже имеет привязку к перенаправлению, поэтому любая ссылка на v12 будет перенаправлена ​​на v14.

Вам не нужно ничего конфигурировать.

Единственные ситуации, когда вам нужно усложняться, - это

  • Экземпляры, в которых что-то будет работать в 2007 году, но не в 2010 году (я не могу подумайте о чем-нибудь, что нужно).

  • Где вы можете использовать специфические функции 2010 года.

Если это так, то то, что я лично сделаю, это двойное компиляция. Измените файл .csproj, чтобы создать 2 несколько разных версии, используйте параметр и условную компиляцию (как и вы, например, С#if DEBUG) для конкретных версий кода, где это необходимо (их будет очень мало). Вы также можете использовать эти условия в ссылках в .csproj, например.

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

Недостатки

  • В итоге вы получаете 2 версии своих Программа

Преимущества

  • Вы получаете 2 версии своей программы! Многие изменения, которые вы, возможно, захотите сделать в версии 2010, будут представлены в файле manifestet.xml, feature.xml и других конфигурационных файлах - отражении, инъекции зависимостей и т.д. Здесь ничего не будет сделано.
  • Все еще есть одна версия исходного кода (с незначительной условной компиляцией)
  • Компилятор выберет больше ошибок (он не может, например, выяснить во время компиляции, что эта напуганная вещь, которую вы делаете с Reflection для вызова нового метода в v14, действительно будет работать)

Ответ 2

Вам нужно использовать отражение. Посмотрите Assembly.LoadFile и Assembly.Load.

Если вам нужно работать с методами класса, вы можете использовать его следующим образом:

        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
        }

Ответ 3

В качестве AppDomain.AssemblyResolve вы можете проверить наличие DLL и вернуться в зависимости от того, какой из них присутствует:

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!
    }
};

В этом случае перенаправление с привязкой к сборке не будет работать для вас, потому что это статично в вашем файле конфигурации, и вы хотите, чтобы это динамически работало на любой машине с SP2007 или SP2010.

Ответ 4

Я думаю, вам нужно посмотреть перенаправление привязки сборки в рамках.

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

Чтобы настроить перенаправление, вы можете использовать инструмент настройки .net framework.

Ответ 5

Это звучит как отличный случай для Injection Dependency с использованием одной из фреймворков DI, таких как Unity или Замок Виндзор. Есть и другие, но я уже рискую религиозной войной, просто упомянув об этих двух.:)