当前位置:网站首页>0x02 - create and cache object visitors

0x02 - create and cache object visitors

2020-12-14 23:27:43 Newbe36524

Create and cache Object Visitor.

It's all about being more efficient

Previous articles , We use a simple example to show how to use Object Visitor to  OrderInfo  All properties of the link and output .

Although the effect has been achieved , But in order to simplify the space, there are still some poor performance practices , In this section, we will introduce the use of Newbe.ObjectVisitor A truly complete posture .

cache Object Visitor

The core code of the previous section is as follows :

var sb2 = new StringBuilder();
var visitor = order.V()
    .ForEach((name, value) => sb2.AppendFormat("{0}: {1}{2}", name, value, Environment.NewLine));
visitor.Run();
Console.WriteLine(sb2.ToString());

In this code , We directly created a object visitor , And then use it directly later , And then the method just ends .

For disposable use object visitor Come on , There's no problem with that . But if the code is on a common hotspot path , This repeats the creation of object visitor There is no doubt that it is a waste . therefore , We can think about caching object visitor In static fields .

therefore , We've got the following code :

using System;
using System.Text;
using Newbe.ObjectVisitor;

namespace yueluo_dalao_yes
{
    class Program
    {
        private static readonly StringBuilder _sb = new StringBuilder();
        private static readonly ICachedObjectVisitor<OrderInfo> _visitor = default(OrderInfo).V()
                .ForEach((name, value) => _sb.AppendFormat("{0}: {1}{2}", name, value, Environment.NewLine))
                .Cache();

        static void Main(string[] args)
        {
            var order = new OrderInfo
            {
                OrderId = 1,
                Buyer = "yueluo",
                TotalPrice = 62359.1478M
            };

            _visitor.Run(order);
            Console.WriteLine(_sb.ToString());
        }
    }

    public class OrderInfo
    {
        public int OrderId { get; set; }
        public string Buyer { get; set; }
        public decimal TotalPrice { get; set; }
    }
}

here , We made these changes :

  1. take object visitor Changed to a static field , And use field initialization to assign values .
  2. initialization object visitor when , Because of this time  OrderInfo  The object has not yet been determined , Therefore use  default(OrderInfo)  To express object visitor The type of target that needs to be accessed .
  3. We are  ForEach  Behind , Called  Cache  Method to create a cached good object visitor. The implementation details can be explained here : Cache  It's actually compiling an expression into a delegate , In this way, the delegate can be used repeatedly later , To achieve the best performance .
  4. Because it is initialized in a static field , therefore  ForEach  Medium  StringBuilder  The object must also be a static field , So we also define it in  _sb  Field .
  5. Through the above transformation , We can directly use the cached  _visitor  To create a formatted string .

You also need to Extend Object

Last section , We're going through a simple transformation , take object visitor It's cached , Avoid creating many times object visitor The cost of .

however , Left behind a very serious problem :ForEach  Static fields are used directly  _sb  String splicing , This can lead to , Multiple calls  _visitor.Run(order)  Will continue to splice on the original basis . This is obviously unreasonable .

In response to the object visitor During the running process, except for the accessed object (order) In addition to processing , You need an extra object (StringBuilder), We added a new one called Extend Object Characteristics of .

Next , Let's transform the example from the previous section :

using System;
using System.Text;
using Newbe.ObjectVisitor;

namespace yueluo_dalao_yes
{
    class Program
    {
        private static readonly ICachedObjectVisitor<OrderInfo, StringBuilder> _visitor = default(OrderInfo).V()
                .WithExtendObject<OrderInfo, StringBuilder>()
                .ForEach((name, value, sb) => sb.AppendFormat("{0}: {1}{2}", name, value, Environment.NewLine))
                .Cache();

        static void Main(string[] args)
        {
            var order = new OrderInfo
            {
                OrderId = 1,
                Buyer = "yueluo",
                TotalPrice = 62359.1478M
            };

            var sb1 = new StringBuilder();
            _visitor.Run(order, sb1);
            Console.WriteLine(sb1.ToString());

            var sb2 = new StringBuilder();
            _visitor.Run(order, sb2);
            Console.WriteLine(sb2.ToString());
        }
    }

    public class OrderInfo
    {
        public int OrderId { get; set; }
        public string Buyer { get; set; }
        public decimal TotalPrice { get; set; }
    }
}

here , We made these changes :

  1. adopt  WithExtendObject  Extension method , Designated our object visitor You need to pass in a  StringBuilder  Type as Extend Object.
  2. Revised  ForEach  To receive incoming from the outside  StringBuilder, And call its splicing method .
  3. Revised  _visitor.Run  Call method of . because , It's not just about passing  order, There is also a need to pass on  StringBuilder  As Extend Object.
  4. Run this sample , You'll find that the same information is output twice , This is exactly what we want .

adopt Extend Object, We can do that  ForEach  In order to implement some logic .

We can also optimize

We can use generic static classes to cache our object visitor, In this way, we can implement all types of attribute splicing function :

using System;
using System.Text;
using Newbe.ObjectVisitor;

namespace yueluo_dalao_yes
{
    class Program
    {
        static void Main(string[] args)
        {
            var order = new OrderInfo
            {
                OrderId = 1,
                Buyer = "yueluo",
                TotalPrice = 62359.1478M
            };

            Console.WriteLine(order.FormatToString());
        }
    }

    public static class FormatToStringExtensions
    {
        public static string FormatToString<T>(this T obj)
        {
            var sb = new StringBuilder();
            FormatStringVisitor<T>.Instance.Run(obj, sb);
            var re = sb.ToString();
            return re;
        }

        private static class FormatStringVisitor<T>
        {
            internal static readonly ICachedObjectVisitor<T, StringBuilder> Instance = CreateFormatToStringVisitor();

            private static ICachedObjectVisitor<T, StringBuilder> CreateFormatToStringVisitor()
            {
                var re = default(T)!
                    .V()
                    .WithExtendObject<T, StringBuilder>()
                    .ForEach((name, value, s) => s.AppendFormat("{0}:{1}{2}", name, value,
                        Environment.NewLine))
                    .Cache();
                return re;
            }
        }
    }

    public class OrderInfo
    {
        public int OrderId { get; set; }
        public string Buyer { get; set; }
        public decimal TotalPrice { get; set; }
    }
}

here , We made these changes :

  1. We added a  FormatToStringExtensions  Static class to add an extension method  FormatToString, So all types of objects have  FormatToString  This method .
  2. Added one  FormatStringVisitor<T>  Generic static classes , Use it to create and save a object visitor Instance to  Instance  attribute , So each type T There are independent object visitor.
  3. Call... Where formatting is needed  FormatToString  Method , You can complete the same logic you need to implement earlier .

This is the final complete plan . actually ,FormatToString  The method is already in Newbe.ObjectVisitor There is a built-in , The implementation method is as described above :

Click here to see FormatToStringExtensions Source code

Summary of this article

Through this article , We've used it through a series of optimizations object visitor The best paradigm for .

The best paradigm has been able to be applied in most scenarios .

Of course , There are more advanced uses waiting for you to discover .

You can click here to see whether to use caching or not object visitor The benchmark of

Release notes

Use samples

Development documents may change with version , To view the latest development documents, you need to step forward  http://cn.ov.newbe.pro

Share with others

GitHub Project address :https://github.com/newbe36524/Newbe.ObjectVisitor

Gitee Project address :https://gitee.com/yks/Newbe.ObjectVisitor

Newbe.ObjectVisitor

 
 
------ In this paper, the end ------

版权声明
本文为[Newbe36524]所创,转载请带上原文链接,感谢
https://chowdera.com/2020/12/202012142327317861.html

随机推荐