在Autofac中可视化依赖树深度 [英] Visualizing dependency tree depth in autofac

查看:126
本文介绍了在Autofac中可视化依赖树深度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我可能一直在寻找错误的内容,在错误的框中寻找内容.但是我似乎找不到一种很好的方法来可视化C#中依赖树的深度.

I may have been searching for the wrong stuff, looking in the wrong boxes. But I can't seem to find a good way to visualize how deep my dependecy tree is in C#.

我起初只是尝试与准备活动&来自Autofac的激活事件.但是我不知道这是否足够好.结果看起来有点时髦.似乎准备事件是经常启动的.看来,激活事件仅在实际创建新对象时才激活.

I've initially tried just hooking up on the preparing-event & the activating-event from Autofac. But I can't figure out if this is good enough. The results looks kinda funky. It seems that the preparing-event is initiated too often. And it seems that the activating event is only activated when a new object is actually created.

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

Our code is .NET 4.7.2 We're using Autofac as our container to handle the dependency injection.

有人对我们如何可视化深度有很好的认识吗?也许那里有一些好的代码或产品可以为我们提供帮助?

Does anyone have a good idé for how we can visualize the depth? Maybe there exists some good code or a product out there that can help us?

推荐答案

前一段时间,我对Autofac进行了类似的任务.我最终得到的是以下内容:

Some time ago, I had a similar quest with Autofac. What I ended up with was the following:

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仅解析一次,这意味着下次您请求图形时,将丢失单例.这对我来说不是问题,因为我使用此代码来检测对象图的慢速分解部分.

Do note that this does not exactly what you want, because it is a resolve tricker. This means that a SingleInstance is only resolved once, which means the next time you request the graph, you'll be missing the singletons. This wasn't a problem for me, because I used this code to detect slow-resolving parts of the object graphs.

但是,此代码可能仍会给您一些有关如何执行此操作的想法.

This code might, however, still give you some ideas of how to do this.

这篇关于在Autofac中可视化依赖树深度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆