首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用generics<T>时不注入属性(PropertiesAutowired)

使用generics<T>时不注入属性(PropertiesAutowired)
EN

Stack Overflow用户
提问于 2020-10-14 13:50:53
回答 1查看 79关注 0票数 0

首先,让我们看一下代码:

代码语言:javascript
运行
复制
using System;
using Autofac;

namespace PropertyInjectionAutofacPoC
{
    public interface IInterfaceA { }
    public interface IInterfaceB
    {
        IInterfaceA ClassA { get; set; }
    }

    public class ClassA : IInterfaceA { }
    public class ClassB : IInterfaceB
    {
        public IInterfaceA ClassA { get; set; } // this is injected properly //
    }

    public class Z { }

    public interface IInterfaceC<T> { }
    public interface IInterfaceD<T>
    {
        IInterfaceA ClassA { get; set; }
        IInterfaceC<T> ClassC { get; set; }
    }

    public interface IInterfaceCZ : IInterfaceC<Z> { }

    public abstract class ClassD<T> : IInterfaceD<T>
    {
        public IInterfaceA ClassA { get; set; } // this is not injected, it's always null //
        public IInterfaceC<T> ClassC { get; set; } // this is not injected, it's always null //
    }

    public abstract class ClassC<T> : IInterfaceC<T> { }
    public sealed class ClassCZ : ClassC<Z>, IInterfaceCZ { }

    public interface IRepositoryZ : IInterfaceD<Z> { }
    public sealed class RepositoryZ : ClassD<Z>, IRepositoryZ { }

    internal class Program
    {
        private static IContainer _container;

        private static void Main()
        {
            try
            {
                RegisterServices();

                // it works //
                 var a = _container.Resolve<IInterfaceB>();

                 // it doesn't work //
                 var b = _container.Resolve<IRepositoryZ>(); // ClassC property is null
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
            finally
            {
                DisposeServices();
            }
        }

        private static void RegisterServices()
        {
            var builder = new ContainerBuilder();

            builder.RegisterType<ClassA>().As<IInterfaceA>();
            builder.RegisterType<ClassB>().As<IInterfaceB>().PropertiesAutowired(); // works like a charm //

            builder.RegisterGeneric(typeof(ClassC<>)).As(typeof(IInterfaceC<>)).PropertiesAutowired();
            builder.RegisterGeneric(typeof(ClassD<>)).As(typeof(IInterfaceD<>)).PropertiesAutowired(); // it doesn't work //

            builder.RegisterType<ClassCZ>().As<IInterfaceCZ>();
            builder.RegisterType<RepositoryZ>().As<IRepositoryZ>();

            _container = builder.Build();
        }

        private static void DisposeServices()
        {
            if (_container != null &&
                _container is IDisposable disposable)
                disposable.Dispose();
        }
    }


}

如果我把所有东西都改成构造函数,它就像一个魔咒一样工作,但是,这里使用注入属性的主要思想是为了避免构造函数地狱。

在上面的代码片段中,有一些注释,其中我提到了什么是有效的,什么不是,当没有使用泛型时,属性注入可以正常工作。

所以,我在问你们,我在这里做错了什么,我的代码缺少了什么才能正常工作?

非常感谢!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-10-14 15:07:54

你在这里遇到的问题主要是你在哪里指定了PropertiesAutowired,而不是你要解决的问题。

我已经更新了你的RegisterServices方法,增加了一些注释。

代码语言:javascript
运行
复制
private static void RegisterServices()
{
    var builder = new ContainerBuilder();

    builder.RegisterType<ClassA>().As<IInterfaceA>();
    builder.RegisterType<ClassB>().As<IInterfaceB>().PropertiesAutowired();

    // These registrations aren't really valid. You would never be able to
    // resolve IInterfaceC<> or IInterfaceD<>, because they are abstract classes, so cannot be constructed.
    // You'll always get a NoConstructorsFoundException.
    builder.RegisterGeneric(typeof(ClassC<>)).As(typeof(IInterfaceC<>)).PropertiesAutowired();
    builder.RegisterGeneric(typeof(ClassD<>)).As(typeof(IInterfaceD<>)).PropertiesAutowired();

    builder.RegisterType<ClassCZ>().As<IInterfaceCZ>();

    // When I resolve IRepositoryZ, this is the registration that gets provided. So this is where you need PropertiesAutowired.
    // Just because RepositoryZ derives from ClassD<Z> does not mean it inherits any of its component registration information,
    // which I think is what you may have been expecting.
    //
    // However, the resolve of IRepositoryZ will now throw a NoConstructorFoundException, because when it goes to inject IInterfaceC<Z>
    // onto the property, it hits the invalid registration problem above.
    builder.RegisterType<RepositoryZ>().As<IRepositoryZ>().PropertiesAutowired();

    _container = builder.Build();
}

从根本上说,我认为您可能需要重新调整一些泛型类与具体类的继承。我不认为有一种简单的方法可以像您在这里尝试的那样,通过具体的注册来提供通用服务。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64347367

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档