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.Dispatcher
はCore 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 core
( WPFアプリケーションを残して)に移植することです 。 主要な部分には、 .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を実際に行う価値がある
以下は少なくとも満足すべきアプローチです:
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
{ }
}
NETFULL
とNETCORE
について明確にする私の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
{ }
}
}