首页 新闻 会员 周边 捐助

net core 使用autofac实现注入,自定义一个controller基类使用注入时的问题

0
[已解决问题] 解决于 2018-06-29 14:49

RT, 目前场景是 一个core 2.1 的web程序,使用autofac进行了service的注入(接口),并且在controller 中使用构造函数注入或者属性注入都可以正常work。

此时写了个 baseWebController ,该基类内部需要用到一个 IServiceA 的一个funA()去获取一个 user对象,并保存在基类里,因为有很多controller 都会用到当前这个user对象, 那么问题来了,baseWebController 里边尝试使用属性注入 IServiceA 始终得不到注入的对象,如果改成构造函数注入,那么所有的controller 都要 额外写 构造函数(IServiceA a): base(a) 

感觉这样的改动面是不是有点大了? 有什么合适的解决方案吗?

死神的背影的主页 死神的背影 | 小虾三级 | 园豆:667
提问于:2018-06-27 16:20
< >
分享
最佳答案
0

 

    public interface IEngine {       
T Resolve<T>() where T : class; object Resolve(Type type); IEnumerable<T> ResolveAll<T>(); object ResolveUnregistered(Type type); }
    public class EngineContext
    {
        public static IEngine Create() =>
            Singleton<IEngine>.Instance ?? (Singleton<IEngine>.Instance = new Engine());

        public static void Replace(IEngine engine) => Singleton<IEngine>.Instance = engine;

        public static IEngine Current {
            get {
                if (Singleton<IEngine>.Instance == null) {
                    Create();
                }
                return Singleton<IEngine>.Instance;
            }
        }
    }
 public class Engine : IEngine {   
        private IServiceProvider _serviceProvider { get; set; }

        public virtual IServiceProvider ServiceProvider => _serviceProvider;

        protected IServiceProvider GetServiceProvider() {
            var accessor = ServiceProvider.GetService<IHttpContextAccessor>();
            var context = accessor.HttpContext;
            return context != null ? context.RequestServices : ServiceProvider;
        }
        

        public T Resolve<T>() where T : class {
            return (T)GetServiceProvider().GetRequiredService(typeof(T));
        }

        public object Resolve(Type type) {
            return GetServiceProvider().GetRequiredService(type);
        }

        public IEnumerable<T> ResolveAll<T>() {
            return (IEnumerable<T>)GetServiceProvider().GetService(typeof(T));
        }

        public object ResolveUnregistered(Type type) {
            Exception innerException = null;
            foreach (var constructor in type.GetConstructors()) {
                try {
                    var parameters = constructor.GetParameters().Select(parameter => {
                        var service = Resolve(parameter.ParameterType);
                        if (service == null)
                            throw new Exception("Unknown dependency");
                        return service;
                    });
                    return Activator.CreateInstance(type, parameters.ToArray());
                } catch (Exception ex) {
                    innerException = ex;
                }
            }
            throw new ArgumentException("No constructor was found that had all the dependencies satisfied.", innerException);
        }
    }

 

    public class Singleton<T> : Singleton {
        private static T _instance;
        public static T Instance {
            get => _instance;
            set {
                _instance = value;
                AllSingletons[typeof(T)] = value;
            }
        }
    }


    public class SingletonList<T> : Singleton<IList<T>> {
        static SingletonList() {
            Singleton<IList<T>>.Instance = new List<T>();
        }

        public new static IList<T> Instance => Singleton<IList<T>>.Instance;
    }


    public class SingletonDictionary<TKey, TValue> : Singleton<IDictionary<TKey, TValue>> {
        static SingletonDictionary() {
            Singleton<Dictionary<TKey, TValue>>.Instance = new Dictionary<TKey, TValue>();
        }

        public new static IDictionary<TKey, TValue> Instance => Singleton<Dictionary<TKey, TValue>>.Instance;
    }

    public class Singleton {
        static Singleton() {
            AllSingletons = new ConcurrentDictionary<Type, object>();
        }
        public static IDictionary<Type, object> AllSingletons { get; }
    }

在BaseController调用方法

var serviceA = EngineContext.Current.Resolve<IServiceA>();

这个方法提取自nopCommerce,可以在github找到

奖励园豆:5
远扬 | 初学一级 |园豆:30 | 2018-06-28 17:07

多谢,我大概看了一下,我这边目前的实现比较简单粗暴,直接把 IServiceProvider 在startup 那里边 给赋值存到了一个公共静态资源类 里边,然后通过 ServiceProvider.GetRequiredService<接口名>(); 这样来做,大概意思应该是 直接取通道里边的 实例,但也只是个别地方使用, 所以就先这么过去了

死神的背影 | 园豆:667 (小虾三级) | 2018-06-29 14:48
其他回答(4)
0

这得看你的注入代码是咋写的了。

爱编程的大叔 | 园豆:30844 (高人七级) | 2018-06-27 17:00
0

对于 Controller ,如果使用 asp.net core 自带的依赖注入,通过 [FromServices] IServiceA serviceA 这样的方法参数声明就可以

dudu | 园豆:30778 (高人七级) | 2018-06-28 10:10
0

请问下最佳答案中的代码,我在var accessor = ServiceProvider.GetService<IHttpContextAccessor>();这一步报错了啊

wyDuang | 园豆:204 (菜鸟二级) | 2019-06-10 16:11
0

请问你的问题解决了么,我现在也是碰到这样的问题,子类都属性注册没问题,然后基类属性注册出来的为null。场景和你的一样,如果你解决了,能听下解决的那几步代码么。

大灰灰 | 园豆:402 (菜鸟二级) | 2019-07-18 16:52

你解决了吗?我也遇见了 我用的.net core 3.1

支持(0) 反对(0) 快乐的小帅哥 | 园豆:200 (初学一级) | 2019-12-21 14:21
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册