Conditional Code at Runtime

  • Thread starter Thread starter Alan Roberts
  • Start date Start date
A

Alan Roberts

Is it possible to have conditional references and code execution in csharp?
I have an app that plays Windows Media asx streams. It requires WMP 9+ to
be installed for this to work and so this is a pre-requisite for my app.
The app is also capable of playing real audio streams, for which it requires
the codecs from Real Alternative to be installed. With this design, I have
references to both the WMP type library and the RealAudio library defined
for the app.

At the moment, my app will only work if both WMP and the Real codecs are
installed on a given client machine. I would like to make the Real codecs
optional. In order for this to work the code would need to determine at
design time whether these exist and only instantiate objects based on them
if this is the case. Is there any way I can achieve this runtime
intelligence?

Cheers

Alan
 
I have done something similar by creating separate assemblies (one
referencing A (or WMP in your case) and the other referencing B (RP)), that
contain the same types. I then hook the AssemblyResolve event and provide
the one that should be loaded based on runtime checks.

Note that this requires that the assemblies in question are not in the
regular search paths, and you may want to look into the security
ramifications (what if someone replaces your assembly with another?). But
it is a fairly easy solution.
 
Philip Rieck said:
I have done something similar by creating separate assemblies (one
referencing A (or WMP in your case) and the other referencing B (RP)), that
contain the same types. I then hook the AssemblyResolve event and provide
the one that should be loaded based on runtime checks.

You shouldn't have the assemblies contain the same types. Define a base
class or interface, and put a concrete implementation in each assembly.
Then at runtime determine which subtype to load, load its assembly and
create an instance.

EG

In you main assembly

interface Decoder
{
void Decode();
}

In Decoder_WMP.dll

class Decoder_WMP : Decoder
{
void Decode()
{
. . .
}

}

David
 
Thanks guys, I will give it a go.

Alan

David Browne said:
You shouldn't have the assemblies contain the same types. Define a base
class or interface, and put a concrete implementation in each assembly.
Then at runtime determine which subtype to load, load its assembly and
create an instance.

EG

In you main assembly

interface Decoder
{
void Decode();
}

In Decoder_WMP.dll

class Decoder_WMP : Decoder
{
void Decode()
{
. . .
}

}

David
 
David,

Say WMP_Decoder and RP_Decoder are each in their own assemblies.
If I do it this way (as you state below), I'll need something like:

public Decoder GetDecoder()
{
Decoder correctDecoder;
if( some_condition)
{
correctDecoder = new WMP_Decoder();
}
else
{
correctDecoder = new RP_Decoder();
}
return correctDecoder();
}

Now, when this method is JIT-ed, wouldn't both the assemblies need to be
loaded ? If so, this would remove the point - to choose a type at runtime
without loading the assemblies involved. If not, then my tests were
inaccurate (entirely possible)
 
Philip Rieck said:
David,

Say WMP_Decoder and RP_Decoder are each in their own assemblies.
If I do it this way (as you state below), I'll need something like:

public Decoder GetDecoder()
{
Decoder correctDecoder;
if( some_condition)
{
correctDecoder = new WMP_Decoder();
}
else
{
correctDecoder = new RP_Decoder();
}
return correctDecoder();
}

Now, when this method is JIT-ed, wouldn't both the assemblies need to be
loaded ? If so, this would remove the point - to choose a type at runtime
without loading the assemblies involved.

You are correct that the above code requires both assemblies to be loaded,
which defeats the purpose.

To avoid loading both assemblies, you must know that each assembly contains
the target type. Then you load one assembly through reflection, create an
instance of the target type (again through reflection), and cast it to the
base type. Something like

public static Foo loadFoo(string typeName, string assemblyFile)
{
Assembly assembly = Assembly.LoadFile(assemblyFile);
Foo foo = (foo) assembly.CreateInstance(typeName);
return foo;
}

David
 
Back
Top