3

在我开始之前,让我在任何人建议或提出问题之前澄清任何困惑。

这个问题与“Windows Mobile 6 Professional”有关,而不是 Windows Phone 7,它不能移植到 Windows Phone 7,因为它必须继续使用旧设备。

现在,有了它的出路...

我目前正在尝试移植一个 C# 库,我有该库的源代码可以在 Windows Mobile 6 设备上运行,我已经对这些东西进行了编码,看起来就像永远一样,但是我从来没有处理过一件事,直到现在,这就是反思。

现在每个人都知道 .NET 紧凑型框架确实存在一些限制,似乎缺乏对“System.Reflection”命名空间中的许多方法和属性的支持就是其中之一。

该库的实际桌面版本设置为 .NET V2.0,并且我有运行 .NET 3.5 SP1 的设备,所以在大多数情况下,我在让事情正常工作方面几乎没有问题,但似乎不能找到一个明智的方法来使以下 2 块代码正常工作:

        var a = AppDomain.CurrentDomain**.GetAssemblies**();
        foreach (var assembly in a)
        {
            if (assembly is System.Reflection**.Emit.**AssemblyBuilder) continue;
            if (assembly**.GetType().**FullName == "System.Reflection.Emit.InternalAssemblyBuilder") continue;
            if (assembly**.GlobalAssemblyCache** && assembly**.CodeBase** == Assembly.GetExecutingAssembly()**.CodeBase**) continue;

            foreach (var t in GetLoadableTypes(assembly))
            {
                if (t.IsInterface) continue;
                if (t.IsAbstract) continue;
                if (t.IsNotPublic) continue;
                if (!typeof(IGeometryServices).IsAssignableFrom(t)) continue;

                var constuctors = t.GetConstructors();
                foreach (var constructorInfo in constuctors)
                {
                    if (constructorInfo.IsPublic && constructorInfo.GetParameters().Length == 0)
                        return (IGeometryServices)Activator.CreateInstance(t);
                }
            }
        }

        catch (**ReflectionTypeLoadException** ex)
        {
            var types = ex**.Types**;
            IList<Type> list = new List<Type>(types**.Length**);
            foreach (var t in types)
                if (t != null && t**.IsPublic**)
                    list.Add(t);
            return list;
        }

具体来说,上面代码中的粗体项是紧凑框架中似乎不存在的方法和属性,并且在使用智能感知和对象浏览器花费了大量时间之后,我没有找到任何返回(或提供)相同的类型。

那么我的问题如下:

有没有人有在 Compact .NET 框架中使用反射的经验,并且可以建议如何使此代码按预期工作,或者我将不得不开始编写自定义存根和功能来替换缺少的方法。

我知道框架上有一些反射功能,所以我确信必须有一种等效的方法来实现它。

最后一点,对于任何可能识别代码的人。是的,它来自 .NET 拓扑套件,是的,我正在尝试构建一个 WM6 版本的库,所以如果你知道有人已经做过它,请对此发表评论,我'将去看看更简单的路径:-)

==================================================== =====================

发布后更新

看起来“粗体”文本在代码片段中不起作用,因此上述代码中被 ** 包围的那些方法/属性是应该以粗体显示的部分。

4

1 回答 1

1

因此,在研究了一些较旧的构建和实验性 Silverlight 构建之后(显然与 Windows Mobile / CE 有很多相同的限制)

我想出了如何让魔法发挥作用。

第一部分是用代表要搜索的程序集的“程序集”结构填充数组。原来是:

var a = AppDomain.CurrentDomain.GetAssemblies(); 

但由于WM中不存在GetAssemblies ,因此最快的方法是使用以下方法:

var a = new[] {Assembly.GetCallingAssembly(), Assembly.GetExecutingAssembly()}; 

现在在我的情况下,这意味着我有两个相同的程序集,但是如果我从我的主 exe 调用一个程序集,而后者又使用 GeoAPI,那么这里将显示 2 个不同的程序集。

下一个挑战是“剥离”我们不需要检查的程序集:

if (assembly is System.Reflection.Emit.AssemblyBuilder) continue; 

if (assembly.GetType().FullName == System.Reflection.Emit.InternalAssemblyBuilder") continue; 

if (assembly.GlobalAssemblyCache && assembly.CodeBase == Assembly.GetExecutingAssembly().CodeBase) continue; 

第一个和第二个实例从未出现在 WM6 中,因此只需将它们注释掉是安全的。第二个确实有效,但是由于您再也不会在 WM6 上看到任何具有给定检查名称的程序集(由于缺少它),因此您应该可以放心地将其注释掉。我没有评论它,但它也从未被触发为真的。

最后一部分(至少就最初的谜题而言)是这样的:

foreach (var t in GetLoadableTypes(assembly)) 
{ 
  if (t.IsInterface) continue; 
  if (t.IsAbstract) continue; 
  if (t.IsNotPublic) continue; 
  if (!typeof(IGeometryServices).IsAssignableFrom(t)) continue; 

在我最初的尝试中缺少“ isInterface ”和“ isNotPublic ”,但是一旦我设法使用预期的数据类型修复了上面的“ var a ”变量的内容,一切都开始正常工作,没有任何遗漏。

最后一个问题是?这解决了一切吗?嗯,不完全……

事实证明,GeoAPI 中“ ReflectInstance ”方法的全部目的是使用“ IGeometryServices ”接口查找用户定义的“ GeometryFactory ” 。

因为我只反映了我从(上面的var a)调用的程序集,所以没有将' NetTopologySuite '(定义几何工厂的位置)添加到选择列表中(显然CurrentDomain.GetAssemblies 包括这个)

最终结果是我最终还是遇到了异常,因为找不到正确类型的程序集。

然而事实证明,在 GeoAPI 中的“ Geometry ”构造函数中有一个重载,允许您传入GeometryFactory,当您这样做时,它完全忽略了 ReflectInstance 方法,只使用它所告诉的内容。

或者换一种说法,我一开始就不必做任何事情,我可以将方法设置为返回“null”并传入我想使用的几何工厂。

无论如何,如果有人有兴趣,我现在有一份工作副本:

GeoAPI.NET NetTopologySuite Wintellect.PowerCollections

在带有 .NET CF 3.5 的 Windows Mobile 6 和 Windows CE 下构建并运行良好。

于 2012-10-03T09:42:38.210 回答