|
2 | 2 | // The .NET Foundation licenses this file to you under the MIT license. |
3 | 3 |
|
4 | 4 | using System; |
| 5 | +using Microsoft.DotNet.RemoteExecutor; |
5 | 6 | using Xunit; |
6 | 7 | using static Microsoft.Extensions.DependencyInjection.Tests.AsyncServiceScopeTests; |
7 | 8 |
|
@@ -191,6 +192,159 @@ public void CreateFactory_CreatesFactoryMethod() |
191 | 192 | Assert.IsType<ObjectFactory<ClassWithABCS>>(factory2); |
192 | 193 | Assert.IsType<ClassWithABCS>(item2); |
193 | 194 | } |
| 195 | + |
| 196 | + [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] |
| 197 | + [InlineData(true)] |
| 198 | +#if NETCOREAPP |
| 199 | + [InlineData(false)] |
| 200 | +#endif |
| 201 | + public void CreateFactory_RemoteExecutor_CreatesFactoryMethod(bool isDynamicCodeSupported) |
| 202 | + { |
| 203 | + var options = new RemoteInvokeOptions(); |
| 204 | + if (!isDynamicCodeSupported) |
| 205 | + { |
| 206 | + options.RuntimeConfigurationOptions.Add("System.Runtime.CompilerServices.RuntimeFeature.IsDynamicCodeSupported", "false"); |
| 207 | + } |
| 208 | + |
| 209 | + using var remoteHandle = RemoteExecutor.Invoke(static () => |
| 210 | + { |
| 211 | + var factory1 = ActivatorUtilities.CreateFactory(typeof(ClassWithABCS), new Type[] { typeof(B) }); |
| 212 | + var factory2 = ActivatorUtilities.CreateFactory<ClassWithABCS>(new Type[] { typeof(B) }); |
| 213 | + |
| 214 | + var services = new ServiceCollection(); |
| 215 | + services.AddSingleton(new A()); |
| 216 | + services.AddSingleton(new C()); |
| 217 | + services.AddSingleton(new S()); |
| 218 | + using var provider = services.BuildServiceProvider(); |
| 219 | + object item1 = factory1(provider, new[] { new B() }); |
| 220 | + var item2 = factory2(provider, new[] { new B() }); |
| 221 | + |
| 222 | + Assert.IsType<ObjectFactory>(factory1); |
| 223 | + Assert.IsType<ClassWithABCS>(item1); |
| 224 | + |
| 225 | + Assert.IsType<ObjectFactory<ClassWithABCS>>(factory2); |
| 226 | + Assert.IsType<ClassWithABCS>(item2); |
| 227 | + }, options); |
| 228 | + } |
| 229 | + |
| 230 | + [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] |
| 231 | + [InlineData(true)] |
| 232 | +#if NETCOREAPP |
| 233 | + [InlineData(false)] |
| 234 | +#endif |
| 235 | + public void CreateFactory_RemoteExecutor_NullArguments_Throws(bool isDynamicCodeSupported) |
| 236 | + { |
| 237 | + var options = new RemoteInvokeOptions(); |
| 238 | + if (!isDynamicCodeSupported) |
| 239 | + { |
| 240 | + options.RuntimeConfigurationOptions.Add("System.Runtime.CompilerServices.RuntimeFeature.IsDynamicCodeSupported", "false"); |
| 241 | + } |
| 242 | + |
| 243 | + using var remoteHandle = RemoteExecutor.Invoke(static () => |
| 244 | + { |
| 245 | + var factory1 = ActivatorUtilities.CreateFactory(typeof(ClassWithA), new Type[] { typeof(A) }); |
| 246 | + |
| 247 | + var services = new ServiceCollection(); |
| 248 | + using var provider = services.BuildServiceProvider(); |
| 249 | + Assert.Throws<NullReferenceException>(() => factory1(provider, null)); |
| 250 | + }, options); |
| 251 | + } |
| 252 | + |
| 253 | + [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] |
| 254 | + [InlineData(true)] |
| 255 | +#if NETCOREAPP |
| 256 | + [InlineData(false)] |
| 257 | +#endif |
| 258 | + public void CreateFactory_RemoteExecutor_NoArguments_UseNullDefaultValue(bool isDynamicCodeSupported) |
| 259 | + { |
| 260 | + var options = new RemoteInvokeOptions(); |
| 261 | + if (!isDynamicCodeSupported) |
| 262 | + { |
| 263 | + options.RuntimeConfigurationOptions.Add("System.Runtime.CompilerServices.RuntimeFeature.IsDynamicCodeSupported", "false"); |
| 264 | + } |
| 265 | + |
| 266 | + using var remoteHandle = RemoteExecutor.Invoke(static () => |
| 267 | + { |
| 268 | + var factory1 = ActivatorUtilities.CreateFactory(typeof(ClassWithADefaultValue), new Type[0]); |
| 269 | + |
| 270 | + var services = new ServiceCollection(); |
| 271 | + using var provider = services.BuildServiceProvider(); |
| 272 | + var item = (ClassWithADefaultValue)factory1(provider, null); |
| 273 | + Assert.Null(item.A); |
| 274 | + }, options); |
| 275 | + } |
| 276 | + |
| 277 | + [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] |
| 278 | + [InlineData(true)] |
| 279 | +#if NETCOREAPP |
| 280 | + [InlineData(false)] |
| 281 | +#endif |
| 282 | + public void CreateFactory_RemoteExecutor_NoArguments_ThrowRequiredValue(bool isDynamicCodeSupported) |
| 283 | + { |
| 284 | + var options = new RemoteInvokeOptions(); |
| 285 | + if (!isDynamicCodeSupported) |
| 286 | + { |
| 287 | + options.RuntimeConfigurationOptions.Add("System.Runtime.CompilerServices.RuntimeFeature.IsDynamicCodeSupported", "false"); |
| 288 | + } |
| 289 | + |
| 290 | + using var remoteHandle = RemoteExecutor.Invoke(static () => |
| 291 | + { |
| 292 | + var factory1 = ActivatorUtilities.CreateFactory(typeof(ClassWithA), new Type[0]); |
| 293 | + |
| 294 | + var services = new ServiceCollection(); |
| 295 | + using var provider = services.BuildServiceProvider(); |
| 296 | + var ex = Assert.Throws<InvalidOperationException>(() => factory1(provider, null)); |
| 297 | + Assert.Equal($"Unable to resolve service for type '{typeof(A).FullName}' while attempting to activate '{typeof(ClassWithA).FullName}'.", ex.Message); |
| 298 | + }, options); |
| 299 | + } |
| 300 | + |
| 301 | + [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] |
| 302 | + [InlineData(true)] |
| 303 | +#if NETCOREAPP |
| 304 | + [InlineData(false)] |
| 305 | +#endif |
| 306 | + public void CreateFactory_RemoteExecutor_NullArgument_UseDefaultValue(bool isDynamicCodeSupported) |
| 307 | + { |
| 308 | + var options = new RemoteInvokeOptions(); |
| 309 | + if (!isDynamicCodeSupported) |
| 310 | + { |
| 311 | + options.RuntimeConfigurationOptions.Add("System.Runtime.CompilerServices.RuntimeFeature.IsDynamicCodeSupported", "false"); |
| 312 | + } |
| 313 | + |
| 314 | + using var remoteHandle = RemoteExecutor.Invoke(static () => |
| 315 | + { |
| 316 | + var factory1 = ActivatorUtilities.CreateFactory(typeof(ClassWithStringDefaultValue), new[] { typeof(string) }); |
| 317 | + |
| 318 | + var services = new ServiceCollection(); |
| 319 | + using var provider = services.BuildServiceProvider(); |
| 320 | + var item = (ClassWithStringDefaultValue)factory1(provider, new object[] { null }); |
| 321 | + Assert.Equal("DEFAULT", item.Text); |
| 322 | + }, options); |
| 323 | + } |
| 324 | + |
| 325 | + [ConditionalTheory(typeof(RemoteExecutor), nameof(RemoteExecutor.IsSupported))] |
| 326 | + [InlineData(true)] |
| 327 | +#if NETCOREAPP |
| 328 | + [InlineData(false)] |
| 329 | +#endif |
| 330 | + public void CreateFactory_RemoteExecutor_NoParameters_Success(bool isDynamicCodeSupported) |
| 331 | + { |
| 332 | + var options = new RemoteInvokeOptions(); |
| 333 | + if (!isDynamicCodeSupported) |
| 334 | + { |
| 335 | + options.RuntimeConfigurationOptions.Add("System.Runtime.CompilerServices.RuntimeFeature.IsDynamicCodeSupported", "false"); |
| 336 | + } |
| 337 | + |
| 338 | + using var remoteHandle = RemoteExecutor.Invoke(static () => |
| 339 | + { |
| 340 | + var factory1 = ActivatorUtilities.CreateFactory(typeof(A), new Type[0]); |
| 341 | + |
| 342 | + var services = new ServiceCollection(); |
| 343 | + using var provider = services.BuildServiceProvider(); |
| 344 | + var item = (A)factory1(provider, null); |
| 345 | + Assert.NotNull(item); |
| 346 | + }, options); |
| 347 | + } |
194 | 348 | } |
195 | 349 |
|
196 | 350 | internal class A { } |
@@ -265,6 +419,15 @@ public ClassWithA(A a) |
265 | 419 | } |
266 | 420 | } |
267 | 421 |
|
| 422 | + internal class ClassWithADefaultValue |
| 423 | + { |
| 424 | + public A A { get; } |
| 425 | + public ClassWithADefaultValue(A a = null) |
| 426 | + { |
| 427 | + A = a; |
| 428 | + } |
| 429 | + } |
| 430 | + |
268 | 431 | internal class ABCS |
269 | 432 | { |
270 | 433 | public A A { get; } |
@@ -354,4 +517,13 @@ public ClassWithABC_DefaultConstructorLast(A a, B b) : base (a, b) { } |
354 | 517 | public ClassWithABC_DefaultConstructorLast(A a) : base(a) { } |
355 | 518 | public ClassWithABC_DefaultConstructorLast() : base() { } |
356 | 519 | } |
| 520 | + |
| 521 | + internal class ClassWithStringDefaultValue |
| 522 | + { |
| 523 | + public string Text { get; set; } |
| 524 | + public ClassWithStringDefaultValue(string text = "DEFAULT") |
| 525 | + { |
| 526 | + Text = text; |
| 527 | + } |
| 528 | + } |
357 | 529 | } |
0 commit comments