Konstantin Koch 8287c54432 Included the Visual Studio extension and made the necessary changes to make it run.
Replaced the old VS templates with ones that offer more flexiblity.
Started replacing the Content Project for the samples with our custom project type.
Inlcuded a basic not yet working AssimpImporter.
2015-04-08 14:50:03 +02:00

264 lines
9.1 KiB
C#

/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Apache License, Version 2.0. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Apache License, Version 2.0, please send an email to
* vspython@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Apache License, Version 2.0.
*
* You must not remove this notice, or any other, from this software.
*
* ***************************************************************************/
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Microsoft.VisualStudio;
using IOleServiceProvider = Microsoft.VisualStudio.OLE.Interop.IServiceProvider;
namespace Microsoft.VisualStudio.Project
{
public class OleServiceProvider : IOleServiceProvider, IDisposable
{
#region Public Types
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")]
public delegate object ServiceCreatorCallback(Type serviceType);
#endregion
#region Private Types
private class ServiceData : IDisposable
{
private Type serviceType;
private object instance;
private ServiceCreatorCallback creator;
private bool shouldDispose;
public ServiceData(Type serviceType, object instance, ServiceCreatorCallback callback, bool shouldDispose)
{
VsUtilities.ArgumentNotNull("serviceType", serviceType);
if ((null == instance) && (null == callback))
{
throw new ArgumentNullException("instance");
}
this.serviceType = serviceType;
this.instance = instance;
this.creator = callback;
this.shouldDispose = shouldDispose;
}
public object ServiceInstance
{
get
{
if (null == instance)
{
instance = creator(serviceType);
System.Diagnostics.Debug.Assert(serviceType != null);
}
return instance;
}
}
public Guid Guid
{
get { return serviceType.GUID; }
}
public void Dispose()
{
if ((shouldDispose) && (null != instance))
{
IDisposable disp = instance as IDisposable;
if (null != disp)
{
disp.Dispose();
}
instance = null;
}
creator = null;
GC.SuppressFinalize(this);
}
}
#endregion
#region fields
private Dictionary<Guid, ServiceData> services = new Dictionary<Guid, ServiceData>();
private bool isDisposed;
/// <summary>
/// Defines an object that will be a mutex for this object for synchronizing thread calls.
/// </summary>
private static volatile object Mutex = new object();
#endregion
#region ctors
public OleServiceProvider()
{
}
#endregion
#region IOleServiceProvider Members
public int QueryService(ref Guid guidService, ref Guid riid, out IntPtr ppvObject)
{
ppvObject = (IntPtr)0;
int hr = VSConstants.S_OK;
ServiceData serviceInstance = null;
if (services != null && services.ContainsKey(guidService))
{
serviceInstance = services[guidService];
}
if (serviceInstance == null)
{
return VSConstants.E_NOINTERFACE;
}
// Now check to see if the user asked for an IID other than
// IUnknown. If so, we must do another QI.
//
if (riid.Equals(NativeMethods.IID_IUnknown))
{
object inst = serviceInstance.ServiceInstance;
if (inst == null)
{
return VSConstants.E_NOINTERFACE;
}
ppvObject = Marshal.GetIUnknownForObject(serviceInstance.ServiceInstance);
}
else
{
IntPtr pUnk = IntPtr.Zero;
try
{
pUnk = Marshal.GetIUnknownForObject(serviceInstance.ServiceInstance);
hr = Marshal.QueryInterface(pUnk, ref riid, out ppvObject);
}
finally
{
if (pUnk != IntPtr.Zero)
{
Marshal.Release(pUnk);
}
}
}
return hr;
}
#endregion
#region Dispose
/// <summary>
/// The IDispose interface Dispose method for disposing the object determinastically.
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
/// <summary>
/// Adds the given service to the service container.
/// </summary>
/// <param name="serviceType">The type of the service to add.</param>
/// <param name="serviceInstance">An instance of the service.</param>
/// <param name="shouldDisposeServiceInstance">true if the Dipose of the service provider is allowed to dispose the sevice instance.</param>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope",
Justification = "The services created here will be disposed in the Dispose method of this type.")]
public void AddService(Type serviceType, object serviceInstance, bool shouldDisposeServiceInstance)
{
// Create the description of this service. Note that we don't do any validation
// of the parameter here because the constructor of ServiceData will do it for us.
ServiceData service = new ServiceData(serviceType, serviceInstance, null, shouldDisposeServiceInstance);
// Now add the service desctription to the dictionary.
AddService(service);
}
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope",
Justification = "The services created here will be disposed in the Dispose method of this type.")]
public void AddService(Type serviceType, ServiceCreatorCallback callback, bool shouldDisposeServiceInstance)
{
// Create the description of this service. Note that we don't do any validation
// of the parameter here because the constructor of ServiceData will do it for us.
ServiceData service = new ServiceData(serviceType, null, callback, shouldDisposeServiceInstance);
// Now add the service desctription to the dictionary.
AddService(service);
}
private void AddService(ServiceData data)
{
// Make sure that the collection of services is created.
if (null == services)
{
services = new Dictionary<Guid, ServiceData>();
}
// Disallow the addition of duplicate services.
if (services.ContainsKey(data.Guid))
{
throw new InvalidOperationException();
}
services.Add(data.Guid, data);
}
/// <devdoc>
/// Removes the given service type from the service container.
/// </devdoc>
public void RemoveService(Type serviceType)
{
VsUtilities.ArgumentNotNull("serviceType", serviceType);
if (services.ContainsKey(serviceType.GUID))
{
services.Remove(serviceType.GUID);
}
}
#region helper methods
/// <summary>
/// The method that does the cleanup.
/// </summary>
/// <param name="disposing"></param>
protected virtual void Dispose(bool disposing)
{
// Everybody can go here.
if (!this.isDisposed)
{
// Synchronize calls to the Dispose simulteniously.
lock (Mutex)
{
if (disposing)
{
// Remove all our services
if (services != null)
{
foreach (ServiceData data in services.Values)
{
data.Dispose();
}
services.Clear();
services = null;
}
}
this.isDisposed = true;
}
}
}
#endregion
}
}