Created
June 14, 2016 13:59
-
-
Save lbargaoanu/857125af403e0a9abe5c135cd462d8df to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using ... | |
static void Main(string[] args) | |
{ | |
var x = (Microsoft.Office.Interop.Excel._Application) Marshal.GetActiveObject("Excel.Application"); | |
x.ChartDataPointTrack = false; | |
MapperRegistry.Mappers.Add(new ComObjectMapper()); | |
var config = new MapperConfiguration(c => c.CreateMap<Microsoft.Office.Interop.Excel._Application, App>()); | |
config.AssertConfigurationIsValid(); | |
var mapper = config.CreateMapper(); | |
var result = mapper.Map<App>(x); | |
} | |
class ComObjectMapper : IObjectMapper | |
{ | |
private static readonly Func<ITypeInfo, Guid> GetTypeInfoGuid = (Func<ITypeInfo, Guid>) Delegate.CreateDelegate(typeof(Func<ITypeInfo, Guid>), typeof(Marshal).GetMethod("GetTypeInfoGuid", BindingFlags.NonPublic | BindingFlags.Static), throwOnBindFailure: true); | |
private static readonly Type ComObjectType = typeof(object).Assembly.GetType("System.__ComObject"); | |
private static readonly Dictionary<Guid, Type> typesByGuid = GetTypes(); | |
private static Dictionary<Guid, Type> GetTypes() | |
{ | |
var types = | |
from assembly in AppDomain.CurrentDomain.GetAssemblies() | |
from type in assembly.ExportedTypes | |
where type.IsInterface && type.IsImport | |
select type; | |
var typesByGuid = new Dictionary<Guid, Type>(); | |
foreach(var type in types) | |
{ | |
typesByGuid[type.GUID] = type; | |
} | |
return typesByGuid; | |
} | |
/// <summary> | |
/// Exposes objects, methods and properties to programming tools and other | |
/// applications that support Automation. | |
/// </summary> | |
[ComImport()] | |
[Guid("00020400-0000-0000-C000-000000000046")] | |
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] | |
interface IDispatch | |
{ | |
[PreserveSig] | |
int GetTypeInfoCount(out int Count); | |
ITypeInfo GetTypeInfo([MarshalAs(UnmanagedType.U4)] int iTInfo, [MarshalAs(UnmanagedType.U4)] int lcid); | |
[PreserveSig] | |
int GetIDsOfNames( | |
ref Guid riid, | |
[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr)] | |
string[] rgsNames, | |
int cNames, | |
int lcid, | |
[MarshalAs(UnmanagedType.LPArray)] int[] rgDispId); | |
[PreserveSig] | |
int Invoke( | |
int dispIdMember, | |
ref Guid riid, | |
uint lcid, | |
ushort wFlags, | |
ref System.Runtime.InteropServices.ComTypes.DISPPARAMS pDispParams, | |
out object pVarResult, | |
ref System.Runtime.InteropServices.ComTypes.EXCEPINFO pExcepInfo, | |
IntPtr[] pArgErr); | |
} | |
public static Type GetComObjectType(object comObject) | |
{ | |
if(!Marshal.IsComObject(comObject)) | |
{ | |
throw new ArgumentOutOfRangeException(nameof(comObject), "Expected a COM object."); | |
} | |
var dispatch = (IDispatch) comObject; | |
var typeInfo = dispatch.GetTypeInfo(0, 0); | |
var typeGuid = GetTypeInfoGuid(typeInfo); | |
return typesByGuid[typeGuid]; | |
} | |
public bool IsMatch(TypePair context) | |
{ | |
return context.SourceType == ComObjectType; | |
} | |
public static Exception MissingMapException(Type sourceType, Type destinationType) | |
{ | |
var source = sourceType.Name; | |
var destination = destinationType.Name; | |
throw new InvalidOperationException($"Missing map from {source} to {destination}. Create using Mapper.CreateMap<{source}, {destination}>."); | |
} | |
public object Map(ResolutionContext context) | |
{ | |
var sourceType = GetComObjectType(context.SourceValue); | |
var typeMap = context.ConfigurationProvider.ResolveTypeMap(sourceType, context.DestinationType); | |
if(typeMap == null) | |
{ | |
throw MissingMapException(sourceType, context.DestinationType); | |
} | |
var newContext = new ResolutionContext(context.SourceValue, context.DestinationValue, new TypePair(sourceType, context.DestinationType), context); | |
newContext.TypeMap = typeMap; | |
return context.Mapper.Map(newContext); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment