c# - anywhere - dotnet core languages




.netフレームワークから.net core/standardに移植するための準備済みシムを作成または使用する方法は? (2)

どのように作成または使用する準備ができてシムズ .net framework 4.6.1要素( .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.DispatcherCore 2.0実装されていません。

1つは追加しようとする可能性があります:

public enum DispatcherShimPriority
{
    Background
    //...
}

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

このインタフェースの実装は2つあります。

public class DispatcherCore: DispaicherShim;

そして

public class DispatcherFramework: DispaicherShim;

マルチターゲットのプロジェクトでaaクラス( Shimsと呼ぶことにしましょう)が続きます:

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

その結果、異なるAPIで使用できるシムが生成されます。

これは正しいアプローチですか?

実際、このようなシムを作るには多くの日常作業が必要です。 私は、この作業を行う必要はないと感じています。 私はこの問題の解決策があると感じています...

私はMicrosoft.Windows.Compatibilityパッケージを知ってMicrosoft.Windows.Compatibilityます。 この質問は、 WPFが多くのwpf固有の要素に関わっているときの移植に関するものです。 これらの要素はMicrosoft.Windows.Compatibilityパッケージには含まれていませんが、残念ながら.Net Core 2.0へのリターゲティングの候補となるアセンブリ全体で使用されてい.Net Core 2.0 。 つまり、 Microsoft.Windows.Compatibilityないクラスをシミングすることです。

このMicrosoft.Windows.Compatibility.ShimsがありMicrosoft.Windows.Compatibility.Shims 、それが私の場合には役立つかどうかはわかりません。 特に次の文章を読んだ後で:

Microsoft.Windows.Compatibility.Shims :このパッケージはインフラストラクチャサービスを提供し、コードから直接参照するべきではありません。

アップデート:最終的なターゲットが.net core 2.0ことを強調

Upd2:タスク全体は、潜在的なWebクライアントのためにWPFアプリケーションの大部分を.net coreWPFアプリケーションを残して)に移植することです 。 主要な部分には、 .net core用に実装されていない.net framework要素が含まれています。

Upd3:完全な戦略に関するいくつかの言葉:より完全な戦略は共有プロジェクトであり、 この記事の最初のアプローチ(#if)です。 私の戦略には2つの大きなステップがあります:1つは徐々にコードを移植し、ベースライブラリから始まりトップライブラリでfinnishingしますが、スタブとPlatformNotSupportedExceptionを強く使用することです。 2番目のステップは、.NETコア実装によるスタブと例外の代わりにトップライブラリからベースライブラリに移動することです。オンデマンド(!) - すべてのスタブと例外を代入する必要はありません。

Upd4私たちはすでにポータブルテストを移植性のないテストから2つのlibに分割しました。 移植作業中にテストを実行することは非常に重要です。


Standard .Netから.Net Coreへの移行は単に単なるアップグレードではなく、物事をどのようにまとめているかを考慮して、新しいプラットフォームへの移行と呼ぶことができます。 .Netコアへの移行とは、既存のコードをコピーできる新しいフレームワークの学習と作成を意味します。

.Net Core1,1.1,2.0、および2.1の大きな違いのために、これらの移行プロセスのフォームが大きく変更されているため、1つのサイズがすべて「shim」に適合し、何らかの種類のラッパーや移行ツールをすばやく作成できます時代遅れの コードを移行するには、作業が必要です。

いくつかのコアOS APIは類似していますが、多くのフレームワークコードが移動または変更されているため、同様のスワップのような追跡も難しい場合があります。 その違いは、第三者のライブラリなどの使用について言及しないことを確認するために、いくつかのR&Dを実際に行う価値がある


以下は少なくとも満足すべきアプローチです:

チェコ共和国のおかげでFirdaこれは彼の答えです

1)一般的なシムで十分です(スニペットが役立つかもしれません)

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
    { }
}

NETFULLNETCOREについて明確にする私のsdk形式の.csprojファイル:

<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>

1.a)Visual Studio snippets

Drv

#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
        { }
  }
}

シムニップ

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
        {}
  }
}

揺れる

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

shimprop - まだ

2)継承が必要な場合。

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(); }
}

2.a)継承のためのオブジェクト

public class WrapperOne
{
    protected IShimOne It { get; }
    protected WrapperOne(IShimOne it) { It = it; }
    public WrapperOne() { It = ShimFactory.CreateOne(); }
    public void MethodOne() { It.MethodOne(); }
}
public class WrapperTwo: WrapperOne
{
    protected new IShimTwo It => (IShimTwo)base.It;
    protected WrapperTwo(IShimTwo it): base(it) {}
    public WrapperTwo(): base(ShimFactory.CreateTwo()) {}
    public void MethodTwo() { It.MethodTwo(); }

3)GUIコントロール( Eto.Forms )の準備ができた "相手"

(実際にはEto.Formsの方が広いアプリケーションを持っています - シムです)

このフレームワークは、使いやすいAPIを使用して、ネイティブツールキットを使用して複数のプラットフォームで実行されるアプリケーションを構築するために使用できます。 これにより、アプリケーションは、単一のUIコードベースを使用して、すべてのプラットフォーム上でネイティブアプリケーションとして表示され、動作するようになります...

//Not fully implemented, just showing the idea:

#if NETFULL
using System.Windows.Controls;
#elif NETCORE
using Eto.Forms;
#endif

namespace PortabilityLibrary.Shims
{
    public class MenuItemShim : Shim<
#if NETFULL
    MenuItem
#elif NETCORE
    MenuItem
#endif
    >
    {
        public MenuItemShim(EventHandler<EventArgs> dlg)
#if NETFULL
        : base(new MenuItem(/*not implemented*/))
#elif NETCORE
        : base(new ButtonMenuItem(dlg))
#endif
        { }
    }
}




shim