简体   繁体   English

如何制作依赖于System.Drawing命名空间的现有C#代码的Silverlight版本

[英]How to make Silverlight version of existing C# code that relies on System.Drawing namespace

We have pretty much C# 2.0 code that heavily relies on System.Drawing namespace. 我们有很多C#2.0代码,它们严重依赖于System.Drawing命名空间。 Also there is some WinGDI dependencies (via interop). 还有一些WinGDI依赖项(通过互操作)。

How would you recommend to tackle the problem of making functionally equivalent Silverlight version of the code? 您如何建议解决制作功能相当的Silverlight版本代码的问题? We want to reuse code as much as possible because we want to continue develop both versions of the code. 我们希望尽可能多地重用代码,因为我们希望继续开发代码的两个版本。

Maybe there is some articles/books you could recommend? 也许你可以推荐一些文章/书籍?

UPDATE: The code is a non-visual component. 更新:代码是一个非可视组件。 Not an application. 不是申请。 There is no 3rd party dependencies. 没有第三方依赖项。

I have a great experience in creating wpf/silverlight versions of software that used to be built using winforms. 我在创建以前使用winforms构建的wpf / silverlight版软件方面有很棒的经验。 It's sad, but in your case, when you use a lot of interop and System.Drawing things, it's practically impossible to do such a thing. 这很难过,但在你的情况下,当你使用很多互操作和System.Drawing的东西时,实际上不可能做这样的事情。

Of cource, you can always try (and really you always have to) to separate your business logic from interface, but in such situation (I hope a'm wrong!), your interface have to be completely redesigned, because of differences in architecture of winforms and wpf/silverlight. 对于cource,你总是可以尝试(而且实际上你总是必须)将业务逻辑与接口分开,但在这种情况下(我希望是错的!),你的接口必须完全重新设计,因为架构不同winforms和wpf / silverlight。

In my experience, this problem solved in this way: all old winforms components stayed just the same, but all new features were built using wpf with help of injection of wpf controls into winforms application. 根据我的经验,这个问题以这种方式解决了:所有旧的winforms组件都保持不变,但所有新功能都是使用wpf构建的,有助于在winforms应用程序中注入wpf控件。

Yes, sometimes it's weird, but it's really more productive than just waste all your old code and spend huge amount of time and money into new, that does just the same. 是的,有时它很奇怪,但它真的更有效率,而不仅仅是浪费你所有的旧代码,花费大量的时间和金钱到新的,这也是一样的。

If there is no GUI and you are still using lots of System.Drawing I guess what this component does is related to manipualtion of images in memory. 如果没有GUI并且你仍在使用大量的System.Drawing我猜这个组件的作用与内存中图像的操作有关。

If that's the case, due to the very high cost of porting all the code, if at all possible, you can consider to change your architecture. 如果是这种情况,由于移植所有代码的成本非常高,如果可能的话,您可以考虑更改您的架构。

Have the old code in the server side, where you can freely use these APIs, and expose the required functionality to your Silverlight application through some web service. 在服务器端使用旧代码,您可以在其中自由使用这些API,并通过某些Web服务向Silverlight应用程序公开所需的功能。 If the component has no GUI it should be very feasible. 如果组件没有GUI,那么它应该是非常可行的。

Edit: Adding suggestions of how this might be appropriate for developers 编辑:添加有关如何适合开发人员的建议

Maybe this might still work - if your developer plans to deploy this Silverlight control in a web page, then he probably has a web server on which he can place your component to be accessible for the Silverlight code. 也许这可能仍然有效 - 如果您的开发人员计划在网页中部署此Silverlight控件,那么他可能有一个Web服务器,他可以在其上放置您的组件以供Silverlight代码访问。

If the developer plans to deploy your Silverlight code in Out-of-Browser mode, you can make a version that would embed the old component (for example as a COM object). 如果开发人员计划在Out-of-Browser模式下部署Silverlight代码,则可以创建一个嵌入旧组件的版本(例如作为COM对象)。

An addition alternative to the above, would be to host this component yourself on a server, or on some public cloud such as Windows Azure. 除此之外的另一种选择是将自己的组件托管在服务器上或某些公共云(如Windows Azure)上。

This is going to be near impossible as both WPF and Silverlight are fundamentally different than older versions of this. 这几乎是不可能的,因为WPF和Silverlight都与旧版本有根本的不同。 If you really want to be able to develop a desktop and web applications at the same time, you would probably be better off using WPF and Silverlight. 如果您真的希望能够同时开发桌面和Web应用程序,那么使用WPF和Silverlight可能会更好。

Only problem this is reusing code is still difficult because Silverlight doesn't have all of the features that WPF does. 唯一的问题是重用代码仍然很困难,因为Silverlight没有WPF所具有的所有功能。 On top of all of this, the model for accessing data in Silverlight is totally asynchronous. 最重要的是,Silverlight中访问数据的模型完全是异步的。

You would be best off building the application in Silverlight, and then porting that application to WPF. 您最好在Silverlight中构建应用程序,然后将该应用程序移植到WPF。

Probably not the answer you were looking for. 可能不是你想要的答案。

Depending on how your existing code base is architected this may not be possible, but you can load Forms controls inside of WPF see this example . 根据您现有代码库的架构方式,这可能无法实现,但您可以在WPF中加载Forms控件,请参阅此示例 If your legacy code is packaged into controls, you may be able to get a lot of code re-use. 如果您的遗留代码打包到控件中,您可能可以重用大量代码。 I hope this helps. 我希望这有帮助。

Here's another wild idea. 这是另一个疯狂的想法。

Isolate all your System.Drawing , PInvoke, GDI, etc. into a separate component, and wrap it as an ActiveX object. 将所有System.Drawing ,PInvoke,GDI等隔离到一个单独的组件中,并将其包装为ActiveX对象。

Embed the ActiveX object in your web page, and make your Silverlight application consume its services somehow. 在您的网页中嵌入ActiveX对象,并使您的Silverlight应用程序以某种方式使用其服务。 I guess this would require some "plumbing" in the level of the web page (eg a script that would activate the ActiveX object, and expose the results to the Silverlight app through the document or something) 我想这需要在网页的层面上进行一些“管道”(例如,一个会激活ActiveX对象的脚本,并通过文档或其他东西将结果公开给Silverlight应用程序)

This is just an initial thought I had. 这只是我最初的想法。 I guess it can be improved in many ways. 我想它可以在很多方面得到改善。 What do you think? 你怎么看? :) :)

Edit: If it is acceptable for your Silverlight code to run in Out-of-Browser mode, then Silverlight 4 supports embedding an ActiveX control in your Silverlight application. 编辑:如果您的Silverlight代码可以在浏览器外模式下运行,则Silverlight 4支持在Silverlight应用程序中嵌入ActiveX控件。 This just might make it feasible to wrap all your old implementation in some ActiveX and use it from Silverlight. 这可能使得将所有旧实现包装在某些ActiveX中并从Silverlight中使用它是可行的。

First of all, you should accept that some of the features of the original code won't make it to Silverlight version . 首先,您应该接受原始代码的某些功能 不会使其成为Silverlight版本 Interop, reading and writing files - such things are either forbidden because of security reasons or just unsupported. 互操作,读写文件 - 由于安全原因或者不支持,这些内容要么被禁止。

Second thing to have in mind is that your code will be polluted with conditional compilation (in case you want to continue to support building of .NET version from the same code base). 要记住的第二件事是你的代码将被条件编译污染(如果你想继续支持从相同的代码库构建.NET版本)。

And the third thing is - you will have to write some new code (instead of removed code). 第三件事是 - 你必须编写一些新代码(而不是删除代码)。 For example, you might need to create new methods that accept WriteableBitmap instead of methods that accept System.Drawing.Bitmap in order to give users of Silverlight version similar set of features. 例如,您可能需要创建接受WriteableBitmap新方法,而不是接受System.Drawing.Bitmap的方法,以便为Silverlight版本的用户提供类似的功能集。

Ok, let's take a look at what you might need to do in order to create Silverlight version of a .NET library. 好的,我们来看看为创建.NET库的Silverlight版本可能需要做些什么。

  1. Create new project for Silverlight version 为Silverlight版本创建新项目
  2. Add all existing code files to this project as links . 将所有现有代码文件作为链接添加到此项目。
  3. Try to build the project. 尝试构建项目。 Most probably the build will fail with many warning and error messages. 很可能构建将失败,并带有许多警告和错误消息。 Obviously, the goal is to fix all of them. 显然,目标是解决所有问题。

Here is some hints for what can be done to fix common build errors. 以下是可以解决常见构建错误的一些提示。

  1. Remove all using namespace-name directives that are not needed. 删除所有using namespace-name不需要的using namespace-name指令。 Exclude unsupported namespaces with conditional compilation like so: 使用条件编译排除不受支持的命名空间,如下所示:
#if !SILVERLIGHT
    using System.Drawing;
#endif
  1. If you are using enumerations that are missing in Silverlight (eg System.Drawing.Imaging.ImageFormat ) then introduce equvalent custom enumerations (eg MyImageFormat ) and change internal code to use only custom enumerations. 如果您使用的是Silverlight中缺少的枚举(例如System.Drawing.Imaging.ImageFormat ),则引入等价的自定义枚举(例如MyImageFormat )并更改内部代码以仅使用自定义枚举。 Add overloaded methods that use custom enumerations (or equivalent Silverlight enumerations) to public interface, if needed. 如果需要,将使用自定义枚举(或等效的Silverlight枚举)的重载方法添加到公共接口。

  2. Do likewise for the structs (eg System.Drawing.PointF ) or change the code to use simpler types (eg two float s instead of PointF structure) 同样对于结构(例如System.Drawing.PointF )或更改代码以使用更简单的类型(例如,两个float而不是PointF结构)

  3. Exclude public and private code that uses unsupported structures with conditional compilation. 排除使用条件编译的不受支持的结构的公共和私有代码。 Consider rewriting internal code so it will use only language constructs supported in .NET and Silverlight. 考虑重写内部代码,以便它只使用.NET和Silverlight支持的语言结构。

  4. Create a wrapper class for accessing embedded resources in Silverlight version because there won't be any ready-made wrappers that give you byte[] or string for binary and text resources. 创建一个包装类,用于访问Silverlight版本中的嵌入式资源,因为不会有任何现成的包装器为二进制文本和文本资源提供byte[]string

  5. Create a property like this 创建这样的属性

public static Encoding DefaultEncoding
    {
        get
        {
    #if SILVERLIGHT
            return Encoding.UTF8;
    #else
            return Encoding.Default;
    #endif
        }
    }

And use this property instead of Encoding.Default in your code. 并在代码中使用此属性而不是Encoding.Default

Sooner or later you will be able to create Silverlight version of your code. 迟早你将能够创建代码的Silverlight版本。 This version will probably have less features but, hey, Silverlight is not a full-blown .NET. 这个版本可能会有更少的功能,但是,嘿,Silverlight并不是一个完整的.NET。 Some features will even be unnecessary in Silverlight. Silverlight中甚至不需要某些功能。 For some original features you might later add equivalent ones. 对于某些原始功能,您可能稍后添加相同的功能。

If you are using nunit for unit-testing your .NET version then you might want to take a look at nunit-silverlight (check this page too) for testing Silverlight version. 如果您使用nunit对.NET版本进行单元测试,那么您可能需要查看nunit-silverlight (也请查看此页面 )来测试Silverlight版本。 There are some caveats, though. 但是有一些警告。

  1. TestCaseSource attribute is unsupported by nunit-silverlight. Nunit-silverlight不支持TestCaseSource属性。
  2. Reading of local files is unsupported. 不支持读取本地文件。

If you need to read or write local files in your tests then you should use Silverlight 4 for your test application. 如果您需要在测试中读取或写入本地文件,则应将Silverlight 4用于测试应用程序。 There is no way to do this in Silverlight 3. You should also setup your test application as Out-of-Browser one and give it elevated trust rights (check "require elevated trust" in Out-of-Browser settings) 在Silverlight 3中无法执行此操作。您还应将测试应用程序设置为浏览器外的一个并为其提供提升的信任权限(在浏览器外设置中选中“需要提升的信任”)

You'll need a wrapper (yeah, another one) for reading and writing local files, because Silverlight tests will be able to consume and produce only byte buffers and streams. 您需要一个包装器(是的,另一个)来读取和写入本地文件,因为Silverlight测试将能够使用并仅生成字节缓冲区和流。

Here are some code snippets that might be useful for the wrapper: 以下是一些可能对包装器有用的代码片段:

Get the path to current folder: 获取当前文件夹的路径:

Uri uri = new Uri(System.Windows.Application.Current.Host.Source, relativeFileName);
var currentPath = uri.OriginalString;

Please note, that you'll need to remove file:// from the beginning of currentPath 请注意,您需要从currentPath的开头删除file://

Reading local files (via COM Automation) 读取本地文件(通过COM Automation)

private static byte[] readBinaryFile(string fileName)
{
    const int adTypeBinary = 1;

    using (dynamic adoCom = System.Runtime.InteropServices.Automation.AutomationFactory.CreateObject(@"ADODB.Stream"))
    {
        adoCom.Type = adTypeBinary;
        adoCom.Open();
        adoCom.LoadFromFile(fileName);

        return adoCom.Read();
    }
}

Writing local files (also via COM Automation) 编写本地文件(也通过COM Automation)

private static void writeBinaryFile(string fileName, byte[] binaryArray)
{
    const int adTypeBinary = 1;
    const int adSaveCreateOverWrite = 2;
    using (dynamic adoCom = System.Runtime.InteropServices.Automation.AutomationFactory.CreateObject(@"ADODB.Stream"))
    {
        adoCom.Type = adTypeBinary;
        adoCom.Open();
        adoCom.Write(binaryArray);
        adoCom.SaveToFile(fileName, adSaveCreateOverWrite);
    }
}

You may also want to check Silverlight COM Toolkit . 您可能还想检查Silverlight COM Toolkit I don't use it, though. 不过我不会用它。

Good luck! 祝好运!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM