-
-
Save domartynov/9d189978573cb31c2792fea6b5a427ef to your computer and use it in GitHub Desktop.
This file contains 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