Created
July 16, 2017 19:33
-
-
Save kbkk/437d92af4f3fc72ee9040f633d0ce988 to your computer and use it in GitHub Desktop.
COM Interop Object Mapper for AutoMapper 6
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 AutoMapper; | |
using System; | |
using System.Collections.Generic; | |
using System.Linq; | |
using System.Runtime.InteropServices; | |
using System.Runtime.InteropServices.ComTypes; | |
using System.Linq.Expressions; | |
using AutoMapper.Execution; | |
using AutoMapper.Internal; | |
using System.Reflection; | |
namespace Anamespace | |
{ | |
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 Expression MapExpression(IConfigurationProvider configurationProvider, ProfileMap profileMap, PropertyMap propertyMap, Expression sourceExpression, Expression destExpression, Expression contextExpression) | |
{ | |
var sourceObject = ExpressionFactory.ToObject(sourceExpression); | |
var sourceType = GetComObjectType(sourceObject); | |
return TypeMapPlanBuilder.MapExpression(configurationProvider, profileMap, | |
new TypePair(sourceType, destExpression.Type), | |
sourceExpression, | |
contextExpression, | |
propertyMap, | |
destExpression | |
); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi Jakub,
The MapExpression method above needs to be changed to accommodate changes for AutoMapper 7.0.1. It needs to be changed to:
Thanks!