سؤال

I need to reference EmguCV from a solution containing one C# WinForms project.

There are four versions of the same library i.e. x86 vand x64, each with and without GPU support. The library requires references to EmguCV's managed DLLs as well as OpenCV's unmanaged DLLs. Copying the correct unmanaged version to the [Bin] folder is easy enough through post-build events.

I want to be able to switch between the managed references easily through code. Maybe something like the following:

public enum EnumEmguCvTarget
{
    None, // Do not use EmguCv
    EmguCvTargetTbb86, // Target EmguCv for x86 without GPU.
    EmguCvTargetGpu86, // Target EmguCv for x86 with GPU.
    EmguCvTargetTbb64, // Target EmguCv for x64 without GPU.
    EmguCvTargetGpu64, // Target EmguCv for x64 with GPU.
}

public EnumEmguCvTarget EmguCvTarget
{ get { return (EnumEmguCvTarget.EmguCvTargetGpu64); } }

Since I am referencing these assemblies at compile time (not late binding), is there a way I can programatically switch between versions based on the value of [EmguCvTarget]?

هل كانت مفيدة؟

المحلول

Step 1: Create interfaces for the objects you're using in EmguCv and place these in a separate AnyCpu project. If there is no common interface for these objects, or when you cannot alter these objects, you'll need to create your own wrapper objects for these classes. It is important that these interfaces are defined in their own assembly, since you'll be referencing this assembly from all your own code.

 public interface IEmguCv{ /* methods and proeprties */ }
 public class EmguCv : IEmguCv { }

Now in your existing application, use Reflection or Activator.CreateInstance to load the correct assembly:

 // which assembly to load depends on your configuration
 Assembly emguAssembly = Assembly.Load("EmguX64");
 Type emguType = emguAssembly.GetType("EmguCvClassYouAddedInterfacesTo");
 IEmguCv object = (IEmguCv)Activator.CreateInstance(emguType);

From here you can use the IEmguCv interface, which will provide you with strong binding, IntelliSense and all the other things you'd expect, but you will be able to load the assembly dynamically based on the context you're under.

Should you need to call a non-default constructor on the EmguCv object, then you can either use the Activator.CreateInstance(Type, Object[], Object[]) overload, or call the constructor through Type.GetConstructor(Type[]).Invoke().

You could also use a library such as Unity or NInject once you have an interface defined, so that you can use these DI containers to do the reflection work for you.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top