How can my C# program behave differently depending on what assemblies are present?
I want to reuse some code logic from a self-hosted web application in my Windows Azure web application. Currently I have code like this:
void myFunction( params )
{
//environment-neutral code
}
I need to rewrite that code to make the program act differently depending on whet开发者_StackOverflowher is is on Azure:
void myFunctionModified( params )
{
if( onAzure() ) {
//run Azure-specific code
} else {
//run non-Azure code
}
}
yes, I know about virtual functions, but I'll need such code for at least instantiating the right object before I can call those virtual functions.
The problem is to implement onAzure()
I need to use stuff from an assembly that is only present on Windows Azure (like RoleEnvironment
for example). So I don't see how I can implement onAzure()
so that it doesn't crash when run outside Windows Azure environment.
How do I make my application act differently depending on what assemblies are present on the system?
Can you use:
Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.IsAvailable
from Determine if app is running in azure or not
If you don't want to include a reference to Microsoft.WindowsAzure.ServiceRuntime in your library, then you could try checking for it in the loaded assemblies using AppDomain.CurrentDomain.GetAssemblies()
and some Linq - e.g.
bool runtimeAvailable = AppDomain.CurrentDomain.GetAssemblies().Any(
assembly => assembly.FullName.StartsWith("Microsoft.Microsoft.WindowsAzure.ServiceRuntime"));
Or you could try loading the Microsoft.WindowsAzure.ServiceRuntime
assembly using Assembly.Load
and checking for a FileNotFoundException
As an alternative/addition to your comment about virtual functions, you could consider using dependency injection.
If you need to write code that conditionally depends on different assemblies, you could use conditional compilation to build different versions of your app to target the two hosting models:
public void MyFunction()
{
#if AZURE
// Code that depends on the Azure assemblies
#elseif
// Code that depends on the .NET Framework assemblies
#end if
}
You could then define a specific build configuration in your project file that defines the AZURE
compiler symbol, like in this example:
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Azure|AnyCPU' ">
<DefineConstants>TRACE;AZURE</DefineConstants>
</PropertyGroup>
If you can't use conditional compilation symbols as other answers have suggested then...
Could you try and get a type using reflection that only exists on Azure? If it can't find the type then you're not on Azure.
Or, if you want to go down the assemblies route, then you could check AppDomain.CurrentDomain.GetAssemblies()
for your Azure assembly.
This really looks like a good case for dependency injection. The functionality that requires Windows Azure RoleEntryPoint or other Windows Azure specific functionality should be tucked behind an interface that is injected (Autofac, Unity, Castle Windsor, Ninject, MEF, etc.). When you build your DI container, you would simply do it differently when deploying to Windows Azure versus on-premises (MyOnPremisesImplementation : IMyFunctionProvider, vs. MyAzureImplementation : IMyFunctionProvider).
精彩评论