Browse Source

Merge pull request #18260 from abpframework/IInjectPropertiesService

Introduce `IInjectPropertiesService`.
pull/18437/head
Halil İbrahim Kalkan 2 years ago
committed by GitHub
parent
commit
c09dd389ce
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 15
      docs/en/Dependency-Injection.md
  2. 44
      framework/src/Volo.Abp.Autofac/Volo/Abp/Autofac/AutoFacInjectPropertiesService.cs
  3. 16
      framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/IInjectPropertiesService.cs
  4. 17
      framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/NullInjectPropertiesService.cs
  5. 67
      framework/test/Volo.Abp.Autofac.Tests/Volo/Abp/Autofac/AutoFacInjectingPropertiesService_Tests.cs

15
docs/en/Dependency-Injection.md

@ -269,6 +269,21 @@ public class MyService : ITransientDependency
} }
```` ````
#### IInjectPropertiesService
You can use the `IInjectPropertiesService` service to inject properties of an object. Generally, it is a service outside of DI, such as manually created services.
````C#
var injectPropertiesService = serviceProvider.GetRequiredService<IInjectPropertiesService>();
var instance = new TestService();
// Set any properties on instance that can be resolved by IServiceProvider.
injectPropertiesService.InjectProperties(instance);
// Set any null-valued properties on instance that can be resolved by the IServiceProvider.
injectPropertiesService.InjectUnsetProperties(instance);
````
### Resolve Service from IServiceProvider ### Resolve Service from IServiceProvider
You may want to resolve a service directly from ``IServiceProvider``. In that case, you can inject `IServiceProvider` into your class and use the ``GetService`` or the `GetRequiredService` method as shown below: You may want to resolve a service directly from ``IServiceProvider``. In that case, you can inject `IServiceProvider` into your class and use the ``GetService`` or the `GetRequiredService` method as shown below:

44
framework/src/Volo.Abp.Autofac/Volo/Abp/Autofac/AutoFacInjectPropertiesService.cs

@ -0,0 +1,44 @@
using System;
using Autofac;
using Autofac.Extensions.DependencyInjection;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Autofac;
public class AutoFacInjectPropertiesService : IInjectPropertiesService, ITransientDependency
{
protected IServiceProvider ServiceProvider { get; }
public AutoFacInjectPropertiesService(IServiceProvider serviceProvider)
{
ServiceProvider = serviceProvider;
}
public virtual TService InjectProperties<TService>(TService instance) where TService : notnull
{
return InjectProperties(instance, false);
}
public virtual TService InjectUnsetProperties<TService>(TService instance) where TService : notnull
{
return InjectProperties(instance, true);
}
protected virtual TService InjectProperties<TService>(TService instance, bool onlyForUnsetProperties)
where TService : notnull
{
if (instance == null)
{
throw new ArgumentNullException(nameof(instance));
}
if (ServiceProvider is not AutofacServiceProvider)
{
throw new AbpException($"The {nameof(ServiceProvider)} must be an instance of {nameof(AutofacServiceProvider)}!");
}
return onlyForUnsetProperties
? ServiceProvider.As<AutofacServiceProvider>().LifetimeScope.InjectUnsetProperties(instance)
: ServiceProvider.As<AutofacServiceProvider>().LifetimeScope.InjectProperties(instance);
}
}

16
framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/IInjectPropertiesService.cs

@ -0,0 +1,16 @@
using System;
namespace Volo.Abp.DependencyInjection;
public interface IInjectPropertiesService
{
/// <summary>
/// Set any properties on <paramref name="instance"/> that can be resolved by IServiceProvider.
/// </summary>
TService InjectProperties<TService>(TService instance) where TService : notnull;
/// <summary>
/// Set any null-valued properties on <paramref name="instance"/> that can be resolved by the IServiceProvider.
/// </summary>
TService InjectUnsetProperties<TService>(TService instance) where TService : notnull;
}

17
framework/src/Volo.Abp.Core/Volo/Abp/DependencyInjection/NullInjectPropertiesService.cs

@ -0,0 +1,17 @@
namespace Volo.Abp.DependencyInjection;
[Dependency(TryRegister = true)]
public class NullInjectPropertiesService : IInjectPropertiesService, ITransientDependency
{
public TService InjectProperties<TService>(TService instance)
where TService : notnull
{
return instance;
}
public TService InjectUnsetProperties<TService>(TService instance)
where TService : notnull
{
return instance;
}
}

67
framework/test/Volo.Abp.Autofac.Tests/Volo/Abp/Autofac/AutoFacInjectingPropertiesService_Tests.cs

@ -0,0 +1,67 @@
using Microsoft.Extensions.DependencyInjection;
using Shouldly;
using Volo.Abp.Autofac.Interception;
using Volo.Abp.DependencyInjection;
using Xunit;
namespace Volo.Abp.Autofac;
public class AutoFacInjectingPropertiesService_Tests : Autofac_Interception_Test
{
[Fact]
public void AutoFacInjectingPropertiesService_Should_Replaces_NullInjectingPropertiesService()
{
ServiceProvider.GetRequiredService<IInjectPropertiesService>().GetType().ShouldBe(typeof(AutoFacInjectPropertiesService));
}
[Fact]
public void InjectProperties()
{
var injectPropertiesService = ServiceProvider.GetRequiredService<IInjectPropertiesService>();
var serviceB = new TestServiceB();
injectPropertiesService.InjectProperties(serviceB);
serviceB.NullTestServiceA.ShouldNotBeNull();
serviceB.NullTestServiceA.Name.ShouldBe("Default Name");
serviceB.NotNullTestServiceA.ShouldNotBeNull();
serviceB.NotNullTestServiceA.Name.ShouldBe("Default Name");
}
[Fact]
public void InjectUnsetProperties()
{
var injectPropertiesService = ServiceProvider.GetRequiredService<IInjectPropertiesService>();
var serviceB = new TestServiceB();
injectPropertiesService.InjectUnsetProperties(serviceB);
serviceB.NullTestServiceA.ShouldNotBeNull();
serviceB.NullTestServiceA.Name.ShouldBe("Default Name");
serviceB.NotNullTestServiceA.ShouldNotBeNull();
serviceB.NotNullTestServiceA.Name.ShouldBe("My Name"); // This is not null property.
}
}
interface ITestServiceA
{
public string Name { get; set; }
}
class TestServiceA : ITestServiceA, ITransientDependency
{
public string Name { get; set; } = "Default Name";
}
interface ITestServiceB
{
}
class TestServiceB : ITestServiceB, ITransientDependency
{
public ITestServiceA NullTestServiceA { get; set; }
public ITestServiceA NotNullTestServiceA { get; set; } = new TestServiceA()
{
Name = "My Name"
};
}
Loading…
Cancel
Save