如何跨命名空间和平台伪造库(GDI 到 Xamarin.Forms),例如重用 Color 结构

Posted

技术标签:

【中文标题】如何跨命名空间和平台伪造库(GDI 到 Xamarin.Forms),例如重用 Color 结构【英文标题】:How to fake a library (GDI to Xamarin.Forms) across namespaces and platforms such as reusing Color struct 【发布时间】:2016-09-27 02:49:09 【问题描述】:

我试图在 Xamarin 中重用旧版 Windows GDI 代码而不修改旧版 GDI 代码(使用 #if 除外)。在这种特定情况下,我需要使用包装在我自己的颜色结构中的 Xamrin.Forms 中的颜色。我收到错误无法转换,如上面问题标题中发布的那样。

这是不被修改(或很少)的遗留代码

#if WINDOWS
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Data;
using System.Windows.Forms;
#else //if Xamarin
using FakeGDI;  //cannot specify 'using Xamarin.Forms;' in legacy class

#endif
namespace LegacyCode

    public class MyClass
    
        public MyClass ()
        
            Color x = Color.Yellow;  //must not change legacy code
        
    

这是使旧版 GDI 调用适应 Xamarin.Forms 的代码

using System;
//cannot specify 'using Xamarin.Forms;' I want to fully qualify Xamarin.Forms as shown below 'Xamarin.Forms.Color.Yellow;'

namespace FakeGDI

    public struct Color
    

        public static Color Yellow 
        
            get  
                return Xamarin.Forms.Color.Yellow;
                ;
        
    

我正在寻找的解决方案是通过我的 Color 结构间接编译和使用 Xamarin.Forms Color 结构。

需要什么才能允许这种类型的转换?

我得到的错误是:无法隐式转换类型Xamarin.Forms.Color' toFakeGDI.Color'

谢谢

【问题讨论】:

"不能指定'使用 Xamarin.Forms;'在遗留类中” - 为什么不呢? 请不要与其他用户串通,多次转发同一个问题。这被认为是 Stack Overflow 上的噪音。如果您的问题因无法回答或没有引起回复而关闭,那么首先要做的是改进问题;对此的一些指导是given here。低质量或无法回答的问题通常会被关闭,但如果改进或澄清(视情况而定)可以重新打开 (***.com/questions/37505910/?noredirect=1)。 【参考方案1】:

在 C# 中绝对不可能做到这一点。

你正在尝试做的事情:

StructA a;
StructB b;
a = b;

In 永远无法工作。只有当 Color 是一个类时才有可能,那么你可以使用继承。

您不能指定“使用 Xamarin.Forms;”的约束在遗留类中并没有给你留下任何方法,因为与 javascript 等语言相比,你不能复制对类的引用,而只能复制到对象。

但是,一个解决方案可能是用不同的语言编写 FakeGDI,这确实允许复制对类的引用。

以下是如何在 JavaScript 中执行此操作的示例,虽然您不能真正在 JavaScript 中执行此操作,但您必须寻找一种可以将其模块保存为 DLL 的动态语言。

module FakeGDI
  var Xamarin = require('Xamarin.Forms.Color.Yellow');

  module.exports = 
      Color : Xamarin.Forms.Color
  ;

【讨论】:

【参考方案2】:

您的代码需要将成员静态属性定义为正确的类型。换句话说:

namespace FakeGDI

    public struct Color
    
        public static Xamarin.Forms.Color Yellow 
        
            get  
                return Xamarin.Forms.Color.Yellow;
            
        
    

请注意,Xamarin.Forms 命名空间应用于静态属性本身。

【讨论】:

谢谢基思。我将它添加为“public static Xamarin.Forms.Color Yellow”,但它没有编译并给出了同样的错误。它为你编译了吗? 不,您的示例代码不足以重现问题(我不知道该代码预期在什么上下文中运行)。如果您可以将最小的复制项目推送到 github 存储库中,那么可能会提供更好的帮助。【参考方案3】:

您看到的异常是因为您的静态属性 FakeGDI.Color.Yellow 的返回类型是 FakeGDI.Color,但您返回的是 Xamarin.Forms.Color 的实例。

首先,您希望静态属性返回您的 Color 类型的实例,因为这是您希望旧代码引用的 Color 类型。然后,您想要定义一个隐式操作符,它将您的 Color 类型转换为 Xamarin Color 类型,无论您的旧代码需要 Xamarin.Forms.Color 但它与您的 FakeGCI.Color 一起提供。

您可以使您的 Color 类型成为 Xamarin Color 类型的包装器,如下所示:

namespace FakeGDI

    public struct Color 
    
        private Xamarin.Forms.Color xamarinColor;

        public static Color Yellow
        
            get
            
                return new Color(Xamarin.Forms.Color.Yellow);
            
        

        private Color(Xamarin.Forms.Color color)
        
            this.xamarinColor = color;
        

        public static implicit operator Xamarin.Forms.Color(Color color)
        
            return color.xamarinColor;
        

        // although serving no purpose in your snippet, your legacy code will
        // likely need to cast from Xamarin Color to your Color type also
        public static implicit operator Color(Xamarin.Forms.Color color)
        
            return new Color(color);
        
    

【讨论】:

@Anna 很高兴为您提供帮助,如果您接受了我的回答,如果它解决了您的问题,将不胜感激 :) 使用 Xamarin.Forms.Color 使用我的 Color 结构是否涉及或调用装箱和拆箱?不只是在我的命名成员下传递值吗?谢谢 这不是装箱,装箱实际上是指将值类型转换为引用类型。我提供的几乎只是语法糖,让您的旧代码与您无法为其添加引用的 Xamarin.Forms.Color 很好地配合使用。编辑:注意颜色是一个结构

以上是关于如何跨命名空间和平台伪造库(GDI 到 Xamarin.Forms),例如重用 Color 结构的主要内容,如果未能解决你的问题,请参考以下文章

如何避免javascript命名空间冲突?

如何跨多个命名空间C#定义和访问嵌套字典数据[重复]

C# - 在共享命名空间中跨文件使用命名空间

如何跨 Namespace 同步 Secret 和 ConfigMap?

ThinPHP命名空间,连接数据库是要修改的配置文件,Model数据模型层,跨控制器调用,如何获取系统常量信息,

如何跨 Namespace 同步 Secret 和 ConfigMap?