如何创建或使用现成的Shim从.net框架移植到.net核心/标准?

时间:2018-09-12 15:27:36

标签: c# .net .net-core porting shim

如何为.net framework 4.6.1元素创建或使用现成的 Shims 将其(从.net framework 4.6.1移植到.net core 2.0 / .net standard 2.0? >


一些感兴趣的课程:,最好为以下课程提供垫片:

System.Windows.Threading.Dispatcher

System.ComponentModel.ItemPropertyInfo.Descriptor

System.Windows.Controls.MenuItem

还有更多...


上下文:

应用程序(代码)不是100%组织良好的。业务逻辑与UI逻辑并非100%分离。答案“先重构”绝对是一个好答案。但就我而言,事情并不是理想情况下的100%。


近似示例,尝试手动进行:

System.Windows.Threading.Dispatcher未在Core 2.0中实现。

可以尝试添加:

public enum DispatcherShimPriority
{
    Background
    //...
}

public interface DispaicherShim
{
    void Invoke(Action action, DispatcherShimPriority prio);
    void BeginInvoke(Action action, DispatcherShimPriority, prio);
}

此接口的两个实现如下:

public class DispatcherCore: DispaicherShim;

public class DispatcherFramework: DispaicherShim;

在多目标项目中紧随其后的是一个类(我们称其为Shims):

public static DispaicherShim CreateDispatcher()
{
#if NETCOREAPP2_0
    return new DispatcherCore();
#else
    return new DispatcherFramework();
#endif       
}

结果是填充程序,可以在不同的API中使用

这是正确的方法吗?


实际上,创建此类垫片需要大量常规工作。我感觉没有必要执行这项工作。我觉得有一个针对此问题的现成解决方案...


我知道Microsoft.Windows.Compatibility软件包。当WPF包含许多特定于wpf的元素时,该问题与移植有关。这些元素不在Microsoft.Windows.Compatibility包中,但是不幸的是,它们在我的程序集中使用,它们是重新定位到.Net Core 2.0的候选对象。我的意思是填充那些不在Microsoft.Windows.Compatibility中的类。

好的,我们有Microsoft.Windows.Compatibility.Shims,但是我不确定它是否对我有用;特别是在阅读了following text之后:

  

Microsoft.Windows.Compatibility.Shims :此程序包提供   基础设施服务,不应直接从中引用   您的代码。...


更新:强调最终目标是.net core 2.0

Upd2 :整个任务是将 WPF 应用程序的主要部分移植到.net core(使正在运行的 WPF 应用程序)作为潜在的网络客户端。主要部分包含.net framework尚未实现的.net core元素。

Upd3 :关于完整策略的几句话:更为完整的策略是Shared projects first approach in this article (#if)。我的策略有2个主要步骤:一个是逐步移植代码,从基础库开始,再在顶级库中进行修饰,但是要大量使用存根和PlatformNotSupportedException。第二步是从顶级库转移到基本库,以.net核心实现替换存根和异常,按需(!)-无需替换所有存根和异常。

Upd4 我们已经将便携式测试与非便携式测试(分为两个库)进行了拆分。在移植过程中运行测试非常重要。

2 个答案:

答案 0 :(得分:4)

从标准.Net迁移到.Net Core不仅仅是升级,考虑到事物的组合方式,您几乎可以称其为向新平台的迁移。转移到.Net核心意味着学习和创建一个新框架,可以在其中复制现有代码。

由于.Net核心1、1.1、2.0和2.1之间的巨大差异,因此迁移过程发生了很大变化,因此没有一种大小适合所有“垫片”,并且具有某种包装器或迁移工具很快就过时了。需要完成迁移代码的工作。

一些核心OS API相似,但是许多框架代码已被移动或更改,因此像进行类似交换一样的追逐也可能很困难。进行一些研发,看看其中的区别更不用说第三方库等的使用,这确实值得。

答案 1 :(得分:0)

以下至少是令人满意的方法:

感谢Firda来自捷克共和国。 This is his answer

1)普通垫片对我来说就足够了(摘要可能会有所帮助)

HashSet<Integer>hashSet=new HashSet<>();
Random random = new Random();
//now add random number to this set
while(true)
{
    hashSet.add(random.nextInt(1000));
    if(hashSet.size()==1000)
        break;
}

示例:

<?php
$json = '{"response":{"result":{"Contacts":{"row":[{"no":"1","FL": 
[{"val":"CONTACTID","content":"3508588000000206016"}, 
{"val":"SMOWNERID","content":"3508588000000176021"},{"val":"Contact 
Owner","content":"Chris Yates"},{"val":"First Name","content":"Bob"}]}]}}}}';
$data = json_decode($json,true);
$rows = $data['response']['result']['Contacts']['row'];
$csvFileName = 'example.csv';
$fp = fopen($csvFileName,'a');
foreach($rows as $row) {
foreach($row['FL'] as $fls) {
    fputcsv($fp, $fls);
}
}
fclose($fp);
?>

我的sdk风格的public abstract class Shim<TImpl> { internal TImpl It { get; } protected Shim(TImpl it) { It = it; } } 文件明确说明了public class DispatcherPriorityShim : Shim< #if NETFULL DispatcherPriority #elif NETCORE string #endif > { public DispatcherPriorityShim(string it) #if NETFULL : base((DispatcherPriority)Enum.Parse(typeof(DispatcherPriority), it)) #elif NETCORE : base(it) #endif { } } .csproj

NETFULL

1.a)Visual Studio snippets

drv

NETCORE

shimenum

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup><TargetFrameworks>netstandard2.0;netcoreapp2.0;net461</TargetFrameworks></PropertyGroup>

  <PropertyGroup Condition=" '$(TargetFramework)' == 'netcoreapp2.0' OR '$(TargetFramework)' == 'netstandard2.0'">
    <DefineConstants>NETCORE;</DefineConstants></PropertyGroup>

  <PropertyGroup Condition=" '$(TargetFramework)' == 'net461'">
    <DefineConstants>NETFULL;</DefineConstants></PropertyGroup>
</Project>

shimnip

#if NETFULL

#elif NETCORE

#endif

假人

namespace PortabilityLibrary.Shims
{
  public class $enumname$Shim : Shim<
#if NETFULL
    $enumname$
#elif NETCORE
    string
#endif
>
  {
        public $enumname$Shim(string it)
#if NETFULL
        : base(($enumname$)Enum.Parse(typeof($enumname$), it))
#elif NETCORE
          : base(it)
#endif
        { }
  }
}

shimprop -尚未


2)需要继承的情况。

namespace PortabilityLibrary.Shims
{
  public class $classname$Shim : Shim<
#if NETFULL
    $classname$
#elif NETCORE
    $classname$
//NullObject
#endif
>
  {
        public $classname$Shim()
#if NETFULL
        : base(new $classname$())
#elif NETCORE
        : base(new $classname$())
    //: base(new NullObject())
#endif
        {}
  }
}

2.a)继承对象

        public void $methodname$()
        {
#if NETFULL
        It.$methodname$();
#elif NETCORE
        It.$methodname$();
        //throw new ShimException();
#endif
        }

3)为GUI控件(Eto.Forms)准备好“对应对象”

(实际上,Eto.Forms具有更广泛的应用-它们是垫片)

  

该框架可用于使用其本机工具包以及易于使用的API来构建在多个平台上运行的应用程序。使用单个UI代码库,这将使您的应用程序在所有平台上看起来都像本机应用程序一样工作。

public interface IShimOne
{
    void MethodOne();
}
public interface IShimTwo: IShimOne
{
    void MethodTwo();
}
#if NETFULL
class One: RealOne, IShimOne {}
class Two: RealTwo, IShimTwo {}
public static class ShimFactory
{
    public static IShimOne CreateOne() { return new One(); }
    public static IShimTwo CreateTwo() { return new Two(); }
}