I have two function that do the exact same thing in two different ways. Each uses a different class to accomplish the task:
void functionA()
{
ClassA a = new ClassA();
a.doWork();
}
void functionB()
{
ClassB b = new ClassB();
b.doSom开发者_StackOverflow中文版ething();
}
this is all in a self contained HttpHandler that can be dropped in any project and work - At least thats the goal. FunctionA would be the preferred way of doing things, FunctionB is a fallback. ClassA might not exist in a given project, ClassB will always exist.
Is there a way at runtime to detect is ClassA exists an use functionA and if not use fcuntionB. Also is there a way to compile this if ClassA doesn't exist? Can I do this with pre-processor stuff (i.e. can I tell at compile time which to include?)
Typically, situations like this are much better handled via Inversion of Control than trying to determine the existence of a class.
Instead of looking for "ClassA" and "ClassB", it would be a better option to provide 2 interfaces that could be implemented. You could then use Dependency Injection to attempt to inject an instance of IInterfaceA
, and if it fails, use an instance of IInterfaceB
instead.
A good articles to read might be Martin Fowler's article on IoC. Also, you may want to look at the Managed Extensibility Framework (now included in .NET 4) which makes this very easy in C#.
If you must do it with the preprocessor #if and #define directives, then in ClassA add
#define ClassA
In your HttpHandler
add
#if ClassA
void function() { ClassA a = new ClassA(); a.doWork(); }
#else
void function() { ClassB b = new ClassB(); b.doSomething(); }
#endif
If possible it would be better to use dependency injection and pass it into the constructor of the HttpHandler
.
You could split your class into two files using the partial
keyword:
// MyClass.cs -- include this into every project
public partial class MyClass {
public void functionB() { ClassB b = new ClassB(); b.doSomething(); }
}
// MyClass.functionA.cs -- include only into projects that have ClassA
public partial class MyClass {
public void functionA() { ClassA a = new ClassA(); a.doWork(); }
}
We do this a few places in our code. I like the "BaseName.Specialty.cs" naming convention, because Solution Explorer will automatically show MyClass.functionA.cs as a sub-node nested under MyClass.cs, the same way it does with .designer.cs files.
You can use reflection (http://msdn.microsoft.com/en-us/library/f7ykdhsy(v=vs.71).aspx). Specifically System.Reflection.Module which can return a list of available types in the module (http://msdn.microsoft.com/en-US/library/system.reflection.module.gettypes(v=VS.80).aspx). I would imagine you can simply cast once you know which type exists.
精彩评论