Property Injection in Asp.Net Core

前端 未结 3 654
北恋
北恋 2020-12-01 10:31

I am trying to port an asp.net application to asp.net core. I have property injection (using ninject) on my UnitOfWork implementation like this.

[Inject]
pu         


        
3条回答
  •  生来不讨喜
    2020-12-01 10:57

    Is there a way to achieve the same functionality using build in DI on .net core?

    No, but here is how you can create your own [inject] attributes with the help of autofac's property injection mecanism.

    First Create your own InjectAttribute:

    [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
    public class InjectAttribute : Attribute
    {
      public InjectAttribute() : base() { }
    }
    

    Then create your own InjectPropertySelector that uses reflection to check for properties marked with [inject]:

    public class InjectPropertySelector : DefaultPropertySelector
    {
      public InjectPropertySelector(bool preserveSetValues) : base(preserveSetValues)
      { }
    
      public override bool InjectProperty(PropertyInfo propertyInfo, object instance)
      {
        var attr = propertyInfo.GetCustomAttribute(inherit: true);
        return attr != null && propertyInfo.CanWrite
                && (!PreserveSetValues
                || (propertyInfo.CanRead && propertyInfo.GetValue(instance, null) == null));
      }
    }
    

    Then use your selector in your ConfigureServices where you wire up your AutofacServiceProvider:

    public class Startup
    {
      public IServiceProvider ConfigureServices(IServiceCollection services)
      {
        var builder = new ContainerBuilder();
        builder.Populate(services);
    
        // use your property selector to discover the properties marked with [inject]
        builder.RegisterType().PropertiesAutowired((new InjectablePropertySelector(true)););
    
        this.ApplicationContainer = builder.Build();
        return new AutofacServiceProvider(this.ApplicationContainer);
      }
    }
    

    Finally in your service you can now use [inject]:

    public class MyServiceX 
    {
        [Inject]
        public IOrderRepository OrderRepository { get; set; }
        [Inject]
        public ICustomerRepository CustomerRepository { get; set; }
    }
    

    You surely can take this solution even further, e.g. by using an attribute for specifying your service's lifecycle above your service's class definition...

    [Injectable(LifetimeScope.SingleInstance)]
    public class IOrderRepository
    

    ...and then checking for this attribute when configuring your services via autofac. But this would go beyond the scope of this answer.

提交回复
热议问题