I'm working on a visual studio add-in that takes SQL queries in your project, plays the request and generates a C# wrapper class for the results. I want to do a simplest possible dependency injection, where projects using my add-in supply a class that can provide the project's db connection string, among other things.
Visual C++ For Mac
I'm planning to do a talk on Dependency Injection and IoC Containers, and I'm looking for some good arguments for using it. What are the most important benefits of using this technique, and these. Dependency Injection mainly reduces the tight coupling between the classes. Dependency Injection moves the abstraction binding out of the class or higher level modules. By Dependency Injection, we can achieve the process of removing the dependency of low level modules from higher level modules. Software Architecture: Dependency Injection for C# Devs 4.2 (130 ratings) Course Ratings are calculated from individual students’ ratings and a variety of other signals, like age of rating and reliability, to ensure that they reflect course quality fairly and accurately.
This interface is defined in my add-in...
And the question : How do I define and instantiate the concrete implementation, then use it from the add-in?
Progress?
The interface above is defined in the add-in. I've created a reference in the target project to the add-in, written the concrete implementation, and put the name of this class in the target project web.config. Now I need to load the target project from the add-in to use my concrete class.
If I use Assembly.Load()...
I can successfully load my class, but I lock the target assembly and can no longer compile the target project.
C# Dependency Injection Frameworks
If I create a temporary app domain...
I get a file not found exception on the call ad.Load(), even though the bytes of my dll are in memory.
If I use CreateInstanceFromAndUnwrap()...

I get an
InvalidCastException. 'Unable to cast transparent proxy to type QueryFirst.IQueryFirst_TargetProject'
This makes me think I'm very close? Why would an explicit cast work fine with Assembly.Load(), but fail when the same assembly is loaded in a newly created AppDomain?
1 Answer
I'm assuming that your add-in is going to be triggered in someway in order to start working with SQL Queries.
I'd recommend that you bundle a separate .exe file with your add-in and do the processing in there.
Here's why:
- Personally, I've had a lot of issues with AppDomains similar to what you're running into with file locking and the head ache of Temp Domains. The other issue you'd likely run into is once you load an Assembly into an AppDomain, you can't unload. By using a separate process (that dies when it's finished) you don't have to worry about the problem.
- Depending on the type of Projects you want to support, those Projects will have dependencies. Managing references to dependent dlls will be a lot easier if you can just point your standalone .exe at a directory (ie the bin directory).
- If you hook into Visual Studio's Build Events (
DTE.Events.BuildEvents.OnBuildBegin) you can kill your process and release the locks on the dll files. Or you could have your process first make copies. - Testing/debugging is a lot easier with a stand alone file. You don't need to worry about trying to debug by attaching to Visual Studio (How to debug a Vsix project).
You can use the following methods to start/kill processes:
I think you can reference the output of a Console Project directly from your VSIX Add In Project via the References Anatomy of a VSIX Package. Otherewise, you might need to do some custom MSBuild to get the .exe included within the VSIX file.
Once it's included, you can find the .exe because it should be in the same path as your executing VSIX (Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) and I would pass it the Path to the loaded Project's bin directory.
As an aside, this isn't Dependency Injection. If you want to use DI inside a VS Extension, you can use whatever framework you'd like, but I think MEF is natively supported. Personally, I prefer Ninject. Define your Kernel inside the Package class and the use it to load your top level class.
Not the answer you're looking for? Browse other questions tagged c#visual-studiovisual-studio-addins or ask your own question.
Xamarin.Mac and .NET Framework 4.5 Frameworks. Other frameworks such as Windows 8, Xamarin.Android and Xamarin.iOS will automatically be included. This is a desktop app that runs on Windows and OSX, and shares code with a PCL.Creating the Solution and Projects
Class Library (Portable) under C#. I did not choose the Class Library (Xamarin.Forms Portable) because I am not referencing that library in my non-mobile application. Name it Portable, select your frameworks and create.Proj. I just wanted to distinguish it from my different projects. All your files are stored in a root folder named Portable. This can be renamed later to match the solution name if desired. I then right-clicked on my solution to add a new project. I chose WPF Application and named it Win. I set it as my startup project. On my OSX Laptop I also opened the same solution in Xamarin Studio. It showed the Win project as unsupported and that’s fine. On the solution I went to Add New Project. Under Mac App I chose a General Empty Project. I named it Mac. Once complete set it as the Startup Project. Back in Windows I reopened my solution it gave me an Unsupported notice and migration report about the Mac project. Disregard.PCL Code
IPlatform. Inside it I created an interface:2 4 | { } |
PlatformManager class with the following code:2 4 6 8 10 12 | { publicPlatformManager(IPlatform platform) _platform=platform; publicDictionary<string,object>GetMachineInfo() returnthis._platform.GetMachineInfo(); } |
StaticUtils2 4 6 8 10 12 14 | { publicstaticvoidAssignPlatformManager(IPlatform platform){ } { { } } |
Windows Project Code
Win project. In my app.xaml.cs file I added the following:2 4 6 8 | privatevoidApplication_Startup(objectsender,StartupEventArgse) //implement the interface Portable.IPlatform implementedInterface=newWinInterface(); //pass in the interface to create a static PlatformManager object to be referenced Portable.StaticUtils.AssignPlatformManager(implementedInterface); |
WinInterface I added this code:2 4 6 8 10 12 14 16 18 20 22 24 | { { varprocessorCnt=Environment.ProcessorCount; varosName='Windows'; varci=newMicrosoft.VisualBasic.Devices.ComputerInfo(); varappVersion=FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).FileVersion; dict['Is64Bit']=is64Bit; dict['MachineName']=machineName; dict['OSVersion']=osVersion; dict['AppVersion']=appVersion; } |
Mac Project Code
AppDelegate.cs file I added the following:2 4 | { Portable.IPlatform implementedInterface=newMacInterface(); Portable.StaticUtils.AssignPlatformManager(implementedInterface); |
MacInterface I added this code:2 4 6 8 10 12 14 16 18 20 22 | { { varprocessorCnt=Environment.ProcessorCount; varosVersion=Foundation.NSProcessInfo.ProcessInfo.OperatingSystemVersionString; varram=Foundation.NSProcessInfo.ProcessInfo.PhysicalMemory; varappVersion=Foundation.NSBundle.MainBundle.ObjectForInfoDictionary('CFBundleShortVersionString').ToString(); dict['Is64Bit']=is64Bit; dict['MachineName']=machineName; dict['OSVersion']=osVersion; dict['AppVersion']=appVersion; } |
How It All Works
StaticUtils class. The assignment method instantiates a new, static PlatformManager for us to reference, and the manager stores the passed interface into a variable within itself. With a static reference we can access it through the life on the application. Now, when we want to fetch our platform method details we reference the static PlatformManager, which references the interface that implements the platform-specific code. Calling it like so will return the desired data:varinfo=StaticUtils.PlatformManager.GetMachineInfo(); |