diff --git a/rd-net/RdFramework.Reflection/RdFramework.Reflection.csproj b/rd-net/RdFramework.Reflection/RdFramework.Reflection.csproj index a984e243..e768ed7b 100644 --- a/rd-net/RdFramework.Reflection/RdFramework.Reflection.csproj +++ b/rd-net/RdFramework.Reflection/RdFramework.Reflection.csproj @@ -1,7 +1,7 @@  - net8.0 + netstandard2.0;net35;net472;net8.0; JetBrains.RdFramework.Reflection JetBrains.Rd.Reflection diff --git a/rd-net/RdFramework.Reflection/ReflectionRdActivator.cs b/rd-net/RdFramework.Reflection/ReflectionRdActivator.cs index fd8b1d69..367c4617 100644 --- a/rd-net/RdFramework.Reflection/ReflectionRdActivator.cs +++ b/rd-net/RdFramework.Reflection/ReflectionRdActivator.cs @@ -148,8 +148,7 @@ private object ActivateRd(Type type) object instance; try { - instance = Activator.CreateInstance(implementingType) - ?? throw new InvalidOperationException($"Unable to create instance of: {implementingType.ToString(true)}"); + instance = Activator.CreateInstance(implementingType)!; } catch (MissingMethodException e) { diff --git a/rd-net/RdFramework.Reflection/ReflectionSerializerVerifier.cs b/rd-net/RdFramework.Reflection/ReflectionSerializerVerifier.cs index 0e0b0164..bff7d55e 100644 --- a/rd-net/RdFramework.Reflection/ReflectionSerializerVerifier.cs +++ b/rd-net/RdFramework.Reflection/ReflectionSerializerVerifier.cs @@ -148,10 +148,7 @@ bool IsValidArray() if (!typeInfo.IsArray) return false; if (typeInfo.GetArrayRank() != 1) return false; - var elementType = typeInfo.GetElementType(); - if (elementType == null) return false; - - var arrayType = elementType.GetTypeInfo(); + var arrayType = typeInfo.GetElementType()!.GetTypeInfo(); return IsFieldType(arrayType, false); } diff --git a/rd-net/RdFramework.Reflection/SerializerReflectionUtil.cs b/rd-net/RdFramework.Reflection/SerializerReflectionUtil.cs index c3e375ac..6e1811ee 100644 --- a/rd-net/RdFramework.Reflection/SerializerReflectionUtil.cs +++ b/rd-net/RdFramework.Reflection/SerializerReflectionUtil.cs @@ -68,14 +68,15 @@ internal static FieldInfo[] GetBindableFields(TypeInfo typeInfo) return list.ToArray(); } - private static IEnumerable GetFields(Type? type, Type baseType) + private static IEnumerable GetFields(Type type, Type baseType) { - foreach (var field in type?.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public) ?? Array.Empty()) + foreach (var field in type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public)) yield return field; // private fields only being returned for the current type - while ((type = type?.BaseType) != baseType && type != null) + while (type.BaseType != baseType && type.BaseType != null) { + type = type.BaseType; // but protected fields are returned in first step foreach (var baseField in type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic)) if (baseField.IsPrivate) diff --git a/rd-net/RdFramework/Impl/EndPointWrapper.cs b/rd-net/RdFramework/Impl/EndPointWrapper.cs index 4a5ada28..2f40c241 100644 --- a/rd-net/RdFramework/Impl/EndPointWrapper.cs +++ b/rd-net/RdFramework/Impl/EndPointWrapper.cs @@ -34,9 +34,10 @@ public static EndPointWrapper CreateIpEndPoint(IPAddress? address = null, int? p }; } - public static EndPointWrapper CreateUnixEndPoint(string? path = null) +#if NET8_0_OR_GREATER + public static EndPointWrapper CreateUnixEndPoint(UnixSocketConnectionParams connectionParams) { - var path1 = path ?? Path.GetTempFileName(); + var path1 = connectionParams.Path ?? Path.GetTempFileName(); return new EndPointWrapper(new UnixDomainSocketEndPoint(path1)) { AddressFamily = AddressFamily.Unix, SocketType = SocketType.Stream, @@ -46,4 +47,10 @@ public static EndPointWrapper CreateUnixEndPoint(string? path = null) LocalPath = path1, }; } + + public struct UnixSocketConnectionParams + { + public string? Path { get; set; } + } +#endif } \ No newline at end of file diff --git a/rd-net/RdFramework/Impl/SocketWire.cs b/rd-net/RdFramework/Impl/SocketWire.cs index 21dec86e..12c3754d 100644 --- a/rd-net/RdFramework/Impl/SocketWire.cs +++ b/rd-net/RdFramework/Impl/SocketWire.cs @@ -525,8 +525,10 @@ public class Client : Base public Client(Lifetime lifetime, IScheduler scheduler, int port, string? optId = null) : this(lifetime, scheduler, EndPointWrapper.CreateIpEndPoint(IPAddress.Loopback, port), optId) {} - public Client(Lifetime lifetime, IScheduler scheduler, string path, string? optId = null) : - this(lifetime, scheduler, EndPointWrapper.CreateUnixEndPoint(path), optId) {} +#if NET8_0_OR_GREATER + public Client(Lifetime lifetime, IScheduler scheduler, EndPointWrapper.UnixSocketConnectionParams connectionParams, string? optId = null) : + this(lifetime, scheduler, EndPointWrapper.CreateUnixEndPoint(connectionParams), optId) {} +#endif public Client(Lifetime lifetime, IScheduler scheduler, EndPointWrapper endPointWrapper, string? optId = null) : base("ClientSocket-"+(optId ?? ""), lifetime, scheduler) @@ -646,7 +648,7 @@ private Server(Lifetime lifetime, IScheduler scheduler, string? optId = null) : public static Socket CreateServerSocket(EndPointWrapper? endPointWrapper) { Protocol.InitLogger.Verbose("Creating server socket on endpoint: {0}", endPointWrapper?.EndPointImpl); - // by default we will use IPEndpoint? + // by default we will use IPEndpoint endPointWrapper ??= EndPointWrapper.CreateIpEndPoint(IPAddress.Loopback, 0); var serverSocket = new Socket(endPointWrapper.AddressFamily, endPointWrapper.SocketType, endPointWrapper.ProtocolType); @@ -673,14 +675,22 @@ private void StartServerSocket(Lifetime lifetime, Socket serverSocket) var thread = new Thread(() => { +#if NET8_0_OR_GREATER Log.Catch(async () => +#else + Log.Catch(() => +#endif { while (lifetime.IsAlive) { try { Log.Verbose("{0} : accepting, port: {1}", Id, Port); +#if NET8_0_OR_GREATER var s = await serverSocket.AcceptAsync(lifetime); +#else + var s = serverSocket.Accept(); +#endif lock (Lock) { if (!lifetime.IsAlive) @@ -751,13 +761,12 @@ public void Deconstruct(out IScheduler scheduler, out string? id) } } - - - public class ServerFactory { [PublicAPI] public readonly int? LocalPort; +#if NET8_0_OR_GREATER [PublicAPI] public readonly string? LocalPath; +#endif [PublicAPI] public readonly IViewableSet Connected = new ViewableSet(); @@ -779,7 +788,9 @@ public ServerFactory( Base.CloseSocket(serverSocket); }); LocalPort = (serverSocket.LocalEndPoint as IPEndPoint)?.Port; +#if NET8_0_OR_GREATER LocalPath = endpointWrapper?.EndPointImpl is UnixDomainSocketEndPoint ? endpointWrapper.LocalPath : null; +#endif void Rec() { diff --git a/rd-net/RdFramework/RdFramework.csproj b/rd-net/RdFramework/RdFramework.csproj index f0f09422..e6ef3b54 100644 --- a/rd-net/RdFramework/RdFramework.csproj +++ b/rd-net/RdFramework/RdFramework.csproj @@ -1,7 +1,7 @@  - net8.0 + netstandard2.0;net35;net472;net8.0 JetBrains.RdFramework JetBrains.Rd diff --git a/rd-net/RdFramework/Tasks/RdFault.cs b/rd-net/RdFramework/Tasks/RdFault.cs index 6d8ead73..b9df4ecc 100644 --- a/rd-net/RdFramework/Tasks/RdFault.cs +++ b/rd-net/RdFramework/Tasks/RdFault.cs @@ -31,8 +31,11 @@ protected RdFault(SerializationInfo info, StreamingContext context) : base(info, ReasonMessage = info.GetString(nameof(ReasonMessage)); } - // [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)] +#if NET8_0_OR_GREATER [Obsolete("This API supports obsolete formatter-based serialization. It should not be called or extended by application code.", DiagnosticId = "SYSLIB0051", UrlFormat = "https://aka.ms/dotnet-warnings/{0}")] +#else + [SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)] +#endif public override void GetObjectData(SerializationInfo info, StreamingContext context) { info.AddValue(nameof(ReasonTypeFqn), ReasonTypeFqn); diff --git a/rd-net/Test.Cross/Test.Cross.csproj b/rd-net/Test.Cross/Test.Cross.csproj index d6b227cb..73f5b25b 100644 --- a/rd-net/Test.Cross/Test.Cross.csproj +++ b/rd-net/Test.Cross/Test.Cross.csproj @@ -1,7 +1,7 @@  - net8.0 + netcoreapp3.1;net8.0 Test.RdCross CrossTests AnyCPU diff --git a/rd-net/Test.RdFramework/SocketProxyTest.cs b/rd-net/Test.RdFramework/SocketProxyTest.cs index 69e91b6c..82f572fa 100644 --- a/rd-net/Test.RdFramework/SocketProxyTest.cs +++ b/rd-net/Test.RdFramework/SocketProxyTest.cs @@ -1,127 +1,127 @@ -// #if !NET35 -// using System.Collections.Generic; -// using System.Threading; -// using JetBrains.Collections.Viewable; -// using JetBrains.Lifetimes; -// using JetBrains.Rd.Base; -// using JetBrains.Rd.Impl; -// using JetBrains.Threading; -// using NUnit.Framework; -// using Test.Lifetimes; -// -// namespace Test.RdFramework -// { -// [TestFixture] -// [Ignore("TODO: this test tends to hang")] -// class SocketProxyTest : LifetimesTestBase -// { -// [Test] -// public void TestSimple() -// { -// // using var factory = Log.UsingLogFactory(new TextWriterLogFactory(Console.Out, LoggingLevel.TRACE)); -// Lifetime.Using(lifetime => -// { -// var proxyLifetimeDefinition = lifetime.CreateNested(); -// var proxyLifetime = proxyLifetimeDefinition.Lifetime; -// { -// SynchronousScheduler.Instance.SetActive(lifetime); -// -// var (serverProtocol, _) = SocketWireIpEndpointTest.Server(lifetime, default); -// -// var proxy = new SocketProxy("TestProxy", proxyLifetime, serverProtocol).With(socketProxy => -// socketProxy.Start()); -// Thread.Sleep(SocketWireIpEndpointTest.DefaultTimeout); -// -// var clientProtocol = SocketWireIpEndpointTest.Client(lifetime, proxy.Port); -// -// var sp = NewRdSignal().Static(1); -// sp.BindTopLevel(lifetime, serverProtocol, SocketWireIpEndpointTest.Top); -// -// var cp = NewRdSignal().Static(1); -// cp.BindTopLevel(lifetime, clientProtocol, SocketWireIpEndpointTest.Top); -// -// var serverLog = new List(); -// var clientLog = new List(); -// -// sp.Advise(lifetime, i => serverLog.Add(i)); -// cp.Advise(lifetime, i => clientLog.Add(i)); -// -// //Connection is established for now -// -// sp.Fire(1); -// -// SpinWaitEx.SpinUntil(() => serverLog.Count == 1); -// SpinWaitEx.SpinUntil(() => clientLog.Count == 1); -// Assert.AreEqual(new List {1}, serverLog); -// Assert.AreEqual(new List {1}, clientLog); -// -// cp.Fire(2); -// -// SpinWaitEx.SpinUntil(() => serverLog.Count == 2); -// SpinWaitEx.SpinUntil(() => clientLog.Count == 2); -// Assert.AreEqual(new List {1, 2}, serverLog); -// Assert.AreEqual(new List {1, 2}, clientLog); -// -// proxy.StopServerToClientMessaging(); -// -// cp.Advise(lifetime, i => Assert.AreNotSame(3, i, "Value {0} mustn't be received", 3)); -// -// sp.Fire(3); -// -// SpinWaitEx.SpinUntil(() => serverLog.Count == 3); -// Assert.AreEqual(new List {1, 2, 3}, serverLog); -// -// -// proxy.StopClientToServerMessaging(); -// -// sp.Advise(lifetime, i => Assert.AreNotSame(4, i, "Value {0} mustn't be received", 4)); -// -// cp.Fire(4); -// -// SpinWaitEx.SpinUntil(() => clientLog.Count == 3); -// Assert.AreEqual(new List {1, 2, 4}, clientLog); -// -// //Connection is broken for now -// -// proxy.StartServerToClientMessaging(); -// -// sp.Fire(5); -// SpinWaitEx.SpinUntil(() => serverLog.Count == 4); -// SpinWaitEx.SpinUntil(() => clientLog.Count == 4); -// Assert.AreEqual(new List {1, 2, 3, 5}, serverLog); -// Assert.AreEqual(new List {1, 2, 4, 5}, clientLog); -// -// -// proxy.StartClientToServerMessaging(); -// -// cp.Fire(6); -// SpinWaitEx.SpinUntil(() => serverLog.Count == 5); -// SpinWaitEx.SpinUntil(() => clientLog.Count == 5); -// Assert.AreEqual(new List {1, 2, 3, 5, 6}, serverLog); -// Assert.AreEqual(new List {1, 2, 4, 5, 6}, clientLog); -// -// //Connection is established for now -// -// proxyLifetimeDefinition.Terminate(); -// -// -// cp.Advise(lifetime, i => Assert.AreNotSame(7, i, "Value {0} mustn't be received", 7)); -// sp.Fire(7); -// -// SpinWaitEx.SpinUntil(() => serverLog.Count == 6); -// Assert.AreEqual(new List {1, 2, 3, 5, 6, 7}, serverLog); -// -// -// sp.Advise(lifetime, i => Assert.AreNotSame(8, i, "Value {0} mustn't be received", 8)); -// cp.Fire(8); -// -// SpinWaitEx.SpinUntil(() => clientLog.Count == 6); -// Assert.AreEqual(new List {1, 2, 4, 5, 6, 8}, clientLog); -// -// //Connection is broken for now, proxy is not alive -// } -// }); -// } -// } -// } -// #endif +#if !NET35 +using System.Collections.Generic; +using System.Threading; +using JetBrains.Collections.Viewable; +using JetBrains.Lifetimes; +using JetBrains.Rd.Base; +using JetBrains.Rd.Impl; +using JetBrains.Threading; +using NUnit.Framework; +using Test.Lifetimes; + +namespace Test.RdFramework +{ + [TestFixture] + [Ignore("TODO: this test tends to hang")] + class SocketProxyTest : LifetimesTestBase + { + [Test] + public void TestSimple() + { + // using var factory = Log.UsingLogFactory(new TextWriterLogFactory(Console.Out, LoggingLevel.TRACE)); + Lifetime.Using(lifetime => + { + var proxyLifetimeDefinition = lifetime.CreateNested(); + var proxyLifetime = proxyLifetimeDefinition.Lifetime; + { + SynchronousScheduler.Instance.SetActive(lifetime); + + var (serverProtocol, _) = SocketWireIpEndpointTest.CreateServer(lifetime); + + var proxy = new SocketProxy("TestProxy", proxyLifetime, serverProtocol).With(socketProxy => + socketProxy.Start()); + Thread.Sleep(SocketWireIpEndpointTest.DefaultTimeout); + + var clientProtocol = SocketWireIpEndpointTest.CreateClient(lifetime, proxy.Port); + + var sp = NewRdSignal().Static(1); + sp.BindTopLevel(lifetime, serverProtocol, SocketWireIpEndpointTest.Top); + + var cp = NewRdSignal().Static(1); + cp.BindTopLevel(lifetime, clientProtocol, SocketWireIpEndpointTest.Top); + + var serverLog = new List(); + var clientLog = new List(); + + sp.Advise(lifetime, i => serverLog.Add(i)); + cp.Advise(lifetime, i => clientLog.Add(i)); + + //Connection is established for now + + sp.Fire(1); + + SpinWaitEx.SpinUntil(() => serverLog.Count == 1); + SpinWaitEx.SpinUntil(() => clientLog.Count == 1); + Assert.AreEqual(new List {1}, serverLog); + Assert.AreEqual(new List {1}, clientLog); + + cp.Fire(2); + + SpinWaitEx.SpinUntil(() => serverLog.Count == 2); + SpinWaitEx.SpinUntil(() => clientLog.Count == 2); + Assert.AreEqual(new List {1, 2}, serverLog); + Assert.AreEqual(new List {1, 2}, clientLog); + + proxy.StopServerToClientMessaging(); + + cp.Advise(lifetime, i => Assert.AreNotSame(3, i, "Value {0} mustn't be received", 3)); + + sp.Fire(3); + + SpinWaitEx.SpinUntil(() => serverLog.Count == 3); + Assert.AreEqual(new List {1, 2, 3}, serverLog); + + + proxy.StopClientToServerMessaging(); + + sp.Advise(lifetime, i => Assert.AreNotSame(4, i, "Value {0} mustn't be received", 4)); + + cp.Fire(4); + + SpinWaitEx.SpinUntil(() => clientLog.Count == 3); + Assert.AreEqual(new List {1, 2, 4}, clientLog); + + //Connection is broken for now + + proxy.StartServerToClientMessaging(); + + sp.Fire(5); + SpinWaitEx.SpinUntil(() => serverLog.Count == 4); + SpinWaitEx.SpinUntil(() => clientLog.Count == 4); + Assert.AreEqual(new List {1, 2, 3, 5}, serverLog); + Assert.AreEqual(new List {1, 2, 4, 5}, clientLog); + + + proxy.StartClientToServerMessaging(); + + cp.Fire(6); + SpinWaitEx.SpinUntil(() => serverLog.Count == 5); + SpinWaitEx.SpinUntil(() => clientLog.Count == 5); + Assert.AreEqual(new List {1, 2, 3, 5, 6}, serverLog); + Assert.AreEqual(new List {1, 2, 4, 5, 6}, clientLog); + + //Connection is established for now + + proxyLifetimeDefinition.Terminate(); + + + cp.Advise(lifetime, i => Assert.AreNotSame(7, i, "Value {0} mustn't be received", 7)); + sp.Fire(7); + + SpinWaitEx.SpinUntil(() => serverLog.Count == 6); + Assert.AreEqual(new List {1, 2, 3, 5, 6, 7}, serverLog); + + + sp.Advise(lifetime, i => Assert.AreNotSame(8, i, "Value {0} mustn't be received", 8)); + cp.Fire(8); + + SpinWaitEx.SpinUntil(() => clientLog.Count == 6); + Assert.AreEqual(new List {1, 2, 4, 5, 6, 8}, clientLog); + + //Connection is broken for now, proxy is not alive + } + }); + } + } +} +#endif diff --git a/rd-net/Test.RdFramework/SocketWireIpEndpointTest.cs b/rd-net/Test.RdFramework/SocketWireIpEndpointTest.cs index ed965072..09cb457d 100644 --- a/rd-net/Test.RdFramework/SocketWireIpEndpointTest.cs +++ b/rd-net/Test.RdFramework/SocketWireIpEndpointTest.cs @@ -24,7 +24,9 @@ internal override int GetPortOrPath() return port; } - internal override (IProtocol ServerProtocol, int portOrPath) Server(Lifetime lifetime, int port = 0) + internal override (IProtocol ServerProtocol, int portOrPath) Server(Lifetime lifetime, int port = 0) => CreateServer(lifetime, port); + + internal static (IProtocol ServerProtocol, int portOrPath) CreateServer(Lifetime lifetime, int port = 0) { var id = "TestServer"; var endPointWrapper = EndPointWrapper.CreateIpEndPoint(IPAddress.Loopback, port); @@ -33,7 +35,9 @@ internal override (IProtocol ServerProtocol, int portOrPath) Server(Lifetime lif return (protocol, server.Port!.Value); } - internal override IProtocol Client(Lifetime lifetime, int port) + internal override IProtocol Client(Lifetime lifetime, int port) => CreateClient(lifetime, port); + + internal static IProtocol CreateClient(Lifetime lifetime, int port) { var id = "TestClient"; var client = new SocketWire.Client(lifetime, SynchronousScheduler.Instance, port, id); diff --git a/rd-net/Test.RdFramework/SocketWireTestBase.cs b/rd-net/Test.RdFramework/SocketWireTestBase.cs index 51f79714..5593de20 100644 --- a/rd-net/Test.RdFramework/SocketWireTestBase.cs +++ b/rd-net/Test.RdFramework/SocketWireTestBase.cs @@ -362,12 +362,15 @@ public void TestSocketFactory() } else { - new SocketWire.Client(lf1.Lifetime, SynchronousScheduler.Instance, factory.LocalPath!); +#if NET8_0_OR_GREATER + var connectionParams = new EndPointWrapper.UnixSocketConnectionParams { Path = factory.LocalPath }; + new SocketWire.Client(lf1.Lifetime, SynchronousScheduler.Instance, connectionParams); SpinWaitEx.SpinUntil(() => factory.Connected.Count == 1); var lf2 = new LifetimeDefinition(); - new SocketWire.Client(lf2.Lifetime, SynchronousScheduler.Instance, factory.LocalPath); + new SocketWire.Client(lf2.Lifetime, SynchronousScheduler.Instance, connectionParams); SpinWaitEx.SpinUntil(() => factory.Connected.Count == 2); +#endif } lf1.Terminate(); diff --git a/rd-net/Test.RdFramework/SocketWireUnixEndpointTest.cs b/rd-net/Test.RdFramework/SocketWireUnixEndpointTest.cs index f333cd30..f485d4ff 100644 --- a/rd-net/Test.RdFramework/SocketWireUnixEndpointTest.cs +++ b/rd-net/Test.RdFramework/SocketWireUnixEndpointTest.cs @@ -1,3 +1,4 @@ +#if NET8_0_OR_GREATER using System.IO; using JetBrains.Collections.Viewable; using JetBrains.Lifetimes; @@ -15,7 +16,8 @@ public class SocketWireUnixEndpointTest : SocketWireTestBase internal override (IProtocol ServerProtocol, string portOrPath) Server(Lifetime lifetime, string path = null) { var id = "TestServer"; - var endPointWrapper = EndPointWrapper.CreateUnixEndPoint(path); + var connectionsParams = new EndPointWrapper.UnixSocketConnectionParams { Path = path }; + var endPointWrapper = EndPointWrapper.CreateUnixEndPoint(connectionsParams); var server = new SocketWire.Server(lifetime, SynchronousScheduler.Instance, endPointWrapper, id); var protocol = new Protocol(id, new Serializers(), new Identities(IdKind.Server), SynchronousScheduler.Instance, server, lifetime); return (protocol, endPointWrapper.LocalPath); @@ -24,11 +26,16 @@ internal override (IProtocol ServerProtocol, string portOrPath) Server(Lifetime internal override IProtocol Client(Lifetime lifetime, string path) { var id = "TestClient"; - var client = new SocketWire.Client(lifetime, SynchronousScheduler.Instance, path, id); + var connectionsParams = new EndPointWrapper.UnixSocketConnectionParams { Path = path }; + var client = new SocketWire.Client(lifetime, SynchronousScheduler.Instance, connectionsParams, id); return new Protocol(id, new Serializers(), new Identities(IdKind.Server), SynchronousScheduler.Instance, client, lifetime); } - internal override EndPointWrapper CreateEndpointWrapper() => EndPointWrapper.CreateUnixEndPoint(); + internal override EndPointWrapper CreateEndpointWrapper() + { + var connectionsParams = new EndPointWrapper.UnixSocketConnectionParams { Path = null }; + return EndPointWrapper.CreateUnixEndPoint(connectionsParams); + } // internal IProtocol Client(Lifetime lifetime, IProtocol serverProtocol) // { @@ -44,4 +51,5 @@ internal override (IProtocol ServerProtocol, IProtocol ClientProtocol) CreateSer var clientProtocol = Client(lifetime, path); return (serverProtocol, clientProtocol); } -} \ No newline at end of file +} +#endif \ No newline at end of file diff --git a/rd-net/Test.RdFramework/Test.RdFramework.csproj b/rd-net/Test.RdFramework/Test.RdFramework.csproj index cf51b457..ec9fe3b2 100644 --- a/rd-net/Test.RdFramework/Test.RdFramework.csproj +++ b/rd-net/Test.RdFramework/Test.RdFramework.csproj @@ -1,7 +1,7 @@  - net8.0 + netcoreapp3.1;net8.0 net472;$(TargetFrameworks);net35 Full diff --git a/rd-net/Test.Reflection.App/Test.Reflection.App.csproj b/rd-net/Test.Reflection.App/Test.Reflection.App.csproj index d29a43d5..ba201a82 100644 --- a/rd-net/Test.Reflection.App/Test.Reflection.App.csproj +++ b/rd-net/Test.Reflection.App/Test.Reflection.App.csproj @@ -2,7 +2,7 @@ Exe - net8.0 + net472;net8.0 false LatestMajor disable diff --git a/rd-net/global.json b/rd-net/global.json new file mode 100644 index 00000000..cf2164e4 --- /dev/null +++ b/rd-net/global.json @@ -0,0 +1,6 @@ +{ + "sdk": { + "version": "8.0.100", + "rollForward": "major" + } +} \ No newline at end of file