Как моя C # программа может вести себя по-разному в зависимости от того, какие сборки присутствуют? - PullRequest
3 голосов
/ 20 июня 2011

Я хочу повторно использовать некоторую логику кода из собственного веб-приложения в моем веб-приложении Windows Azure. В настоящее время у меня есть код, подобный этому:

void myFunction( params )
{
   //environment-neutral code
}

Мне нужно переписать этот код, чтобы программа работала по-разному в зависимости от того, есть ли на Azure:

void myFunctionModified( params )
{
    if( onAzure() ) {
       //run Azure-specific code
    } else {
       //run non-Azure code
    }
}

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

Проблема заключается в реализации onAzure() Мне нужно использовать материал из сборки, которая присутствует только в Windows Azure (например, RoleEnvironment). Поэтому я не понимаю, как реализовать onAzure(), чтобы он не зависал при запуске вне среды Windows Azure.

Как заставить мое приложение работать по-разному в зависимости от того, какие сборки присутствуют в системе?

Ответы [ 4 ]

8 голосов
/ 20 июня 2011

Можете ли вы использовать:

Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.IsAvailable

из Определите, работает ли приложение в лазури или нет


Если вы не хотите включатьссылка на Microsoft.WindowsAzure.ServiceRuntime в вашей библиотеке, тогда вы можете попробовать проверить его в загруженных сборках, используя AppDomain.CurrentDomain.GetAssemblies() и некоторые Linq - например,

bool runtimeAvailable = AppDomain.CurrentDomain.GetAssemblies().Any(
    assembly => assembly.FullName.StartsWith("Microsoft.Microsoft.WindowsAzure.ServiceRuntime"));

или вы можете попробовать загрузить сборку Microsoft.WindowsAzure.ServiceRuntimeиспользуя Assembly.Load и проверяя исключение FileNotFoundException


В качестве альтернативы / дополнения к вашему комментарию о виртуальных функциях, вы можете рассмотреть возможность внедрения зависимости.

3 голосов
/ 20 июня 2011

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

    public void MyFunction()
    {
#if AZURE
        // Code that depends on the Azure assemblies
#elseif
        // Code that depends on the .NET Framework assemblies
#end if
    }

Затем вы можете определить конкретную конфигурацию сборки в вашем файле проекта, которая определяет символ компилятора AZURE, как в этом примере:

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Azure|AnyCPU' ">
    <DefineConstants>TRACE;AZURE</DefineConstants>
</PropertyGroup>
2 голосов
/ 23 июня 2011

Это действительно похоже на хороший случай для внедрения зависимости. Функциональность, для которой требуется Windows Azure RoleEntryPoint или другие специальные функции Windows Azure, должна быть скрыта за внедряемым интерфейсом (Autofac, Unity, Castle Windsor, Ninject, MEF и т. Д.). Когда вы создаете свой DI-контейнер, вы просто делаете это по-разному при развертывании в Windows Azure по сравнению с локальной версией (MyOnPremisesImplementation: IMyFunctionProvider, по сравнению с MyAzureImplementation: IMyFunctionProvider).

2 голосов
/ 20 июня 2011

Если вы не можете использовать условные символы компиляции, как предлагали другие ответы, тогда ...

Не могли бы вы попытаться получить тип с использованием отражения, который существует только в Azure?Если он не может найти тип, значит, вы не в Azure.

Или, если вы хотите пойти по маршруту сборки, тогда вы можете проверить AppDomain.CurrentDomain.GetAssemblies() для вашей сборки Azure.

...