那麼這裏就是我最終將作爲一個概念證明放在一起,只是一些擴展方法,真的。這依賴於實現IPersist
的COM對象,並且在當前的AppDomain
中加載的PIA中的一箇中具有RCW等級。
internal static class ExtensionMethods
{
internal static object ConvertToRCW(this object o)
{
var guid = o.GetCLSID();
if (guid != Guid.Empty)
{
return Marshal.CreateWrapperOfType(o, o.GetTypeFromGuid(guid));
}
else
{
return o;
}
}
internal static Guid GetCLSID(this object o)
{
Guid guid = Guid.Empty;
var p = o as IPersist;
if (p != null)
p.GetClassID(out guid);
return guid;
}
internal static Type GetTypeFromGuid(this object o, Guid guid)
{
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (var assembly in assemblies)
{
var types = assembly.GetLoadableTypes();
foreach (var type in types)
{
if (type.GUID == guid)
return type;
}
}
return o.GetType();
}
internal static IEnumerable<Type> GetLoadableTypes(this Assembly assembly)
{
try
{
return assembly.GetTypes();
}
catch (ReflectionTypeLoadException e)
{
return e.Types.Where(t => t != null);
}
}
}
像這樣來使用:
var point = new ESRI.ArcGIS.Geometry.Point();
point.PutCoords(1, 1);
Console.WriteLine(point.GetType().FullName);
Console.WriteLine(point.Envelope.GetType().FullName);
Console.WriteLine(point.Envelope.ConvertToRCW().GetType().FullName);
我得到以下輸出:
ESRI.ArcGIS.Geometry.PointClass
System.__ComObject
ESRI.ArcGIS.Geometry.EnvelopeClass
這是理想的結果。現在,使用LINQPad(我的original question)這個遊戲很好。
傳遞給CreateWrapperOfType的第二個參數需要在.NET空間中定義(使用ComImport屬性等),所以如果不以某種方式定義此類型(使用C#代碼,tlbimp或Reflection Emit),它將不起作用 –
我有定義RCW的PIA(更多信息請參閱相關問題)。 – blah238
是的,這不會改變答案:-)它仍然是你的工作提供的類型,因爲在.NET空間中可以有一組無限的類型定義相應的COM對象。所以,如果你有PIA,你可以瀏覽PIA命名空間中的所有類(例如使用Reflection),建立一個'Dictionary',並且當你有了這個GUID時,就可以從這個字典中提供這個類型。 –