【问题标题】:Visualizing dependency tree depth in autofac在 autofac 中可视化依赖树深度
【发布时间】:2019-12-09 10:22:41
【问题描述】:

我可能一直在寻找错误的东西,看错了盒子。但我似乎找不到一个很好的方法来可视化我的依赖树在 C# 中的深度。

我最初只是尝试连接 Autofac 的准备事件和激活事件。但我不知道这是否足够好。结果看起来有点时髦。似乎准备事件启动得太频繁了。而且似乎只有在实际创建新对象时才会激活激活事件。

我们的代码是 .NET 4.7.2 我们使用 Autofac 作为我们的容器来处理依赖注入。

有没有人对我们如何可视化深度有很好的了解?也许有一些好的代码或产品可以帮助我们?

【问题讨论】:

    标签: c# .net dependency-injection autofac


    【解决方案1】:

    前段时间,我对 Autofac 有过类似的任务。我最终得到的是以下内容:

    public class DebugResolveModule : Module
    {
        private readonly ThreadLocal<ResolveInfo> _current = new ThreadLocal<ResolveInfo>();
    
        protected override void AttachToComponentRegistration(
            IComponentRegistry componentRegistry, IComponentRegistration registration)
        {
            registration.Preparing += Registration_Preparing;
            registration.Activating += Registration_Activating;
    
            base.AttachToComponentRegistration(componentRegistry, registration);
        }
    
        private void Registration_Preparing(object sender, PreparingEventArgs e)
        {
            _current.Value = new ResolveInfo(e.Component.Activator.LimitType, _current.Value);
        }
    
        private void Registration_Activating(object sender, ActivatingEventArgs<object> e)
        {
            var current = _current.Value;
            current.MarkComponentAsResolved();
            _current.Value = current.Parent;
    
            if (current.Parent == null)
            {
                VisualizeGraph(current);
                Debug.WriteLine(
                    $"total resolve time: {current.ResolveTime.TotalMilliseconds} ms.");
            }
        }
    
        private static void VisualizeGraph(ResolveInfo node, int depth = 0)
        {
            for (int i = 0; i < depth; i++)
            {
                Debug.Write("   ");
            }
    
            Debug.Write(node.ComponentType);
            Debug.Write(" (");
            Debug.Write(node.ResolveTime.TotalMilliseconds.ToString("F1"));
            Debug.Write(" ms. / ");
            Debug.Write(node.CreationTime.TotalMilliseconds.ToString("F1"));
            Debug.Write(" ms.)");
    
    
            Debug.WriteLine("");
    
            foreach (var dependency in node.Dependencies)
            {
                VisualizeGraph(dependency, depth + 1);
            }
        }
    
        private sealed class ResolveInfo
        {
            private Stopwatch _watch = Stopwatch.StartNew();
    
            public ResolveInfo(Type componentType, ResolveInfo parent)
            {
                ComponentType = componentType;
                Parent = parent;
                Dependencies = new List<ResolveInfo>(4);
    
                if (parent != null)
                {
                    parent.Dependencies.Add(this);
                }
            }
    
            public Type ComponentType { get; }
    
            // Time it took to create the type including its dependencies
            public TimeSpan ResolveTime { get; private set; }
    
            // Time it took to create the type excluding its dependencies
            public TimeSpan CreationTime { get; private set; }
            public ResolveInfo Parent { get; }
    
            public List<ResolveInfo> Dependencies { get; }
    
            public void MarkComponentAsResolved()
            {
                ResolveTime = _watch.Elapsed;
                CreationTime = ResolveTime;
    
                foreach (var dependency in this.Dependencies)
                {
                    CreationTime -= dependency.ResolveTime;
                }
                    
                _watch = null;
            }
        }
    }
    

    请注意,这并不完全符合您的要求,因为它是一个解析触发器。这意味着 SingleInstance 只解析一次,这意味着下次您请求图表时,您将丢失单例。这对我来说不是问题,因为我使用此代码来检测对象图的慢速解析部分。

    不过,此代码可能仍会为您提供一些有关如何执行此操作的想法。

    【讨论】:

    • 非常感谢!这是朝着我想去的方向迈出的一大步! :)
    • 您知道为什么我的对象显示为多次解析吗?例如,看起来我的控制器正在调用自己。每个的解析时间都是相同的,但深度不同。如果您需要更多信息,我会创建一个新问题 ;)
    • 对不起@Squazz,这是我前段时间自己使用过这段代码,但请注意,当一个组件注册为InstancePerDependency时,它可以在同一张图。但是如果依赖依赖于 InstancePerLifetimeSingleInstance 依赖,这些依赖将不会在图中被解析两次。这意味着(使用此代码),InstancePerDependency 依赖项的第一个解析似乎比下一个解析具有更多的依赖项,因为此图仅显示解析。也许这就是正在发生的事情。
    • 注明。您描述的场景与我看到的不同,所以我创建了以下问题;)stackoverflow.com/q/59305813
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-09
    • 2016-06-12
    • 1970-01-01
    • 1970-01-01
    • 2013-07-21
    相关资源
    最近更新 更多