Monday, 6 May 2024

FormatterServices.GetUninitializedObject is Obsolete, What can we use instead?

The FormatterServices.GetUninitializedObject is obsolete and shows a warning as shown below if we try to use it in our code. The FormatterServices class is obsolete as per documentation.


What is the alternative for this? Let's find out with an example.

Below is a simple interface.

namespace getuntnitializeobject
{
    public interface IMessage
    {
        string GetEventHubName();
    }
}

Using this interface we have two classes defined as below.

namespace getuntnitializeobject
{
    internal class NewInvoiceMessage : IMessage
    {
        private const string EventHubName = "newinvoice";

        private readonly bool _someOtherSetting;
        public NewInvoiceMessage(bool someOtherSetting)
        {
            _someOtherSetting = someOtherSetting;
        }

        public string GetEventHubName()
        {
            return EventHubName;
        }
    }
}


namespace getuntnitializeobject
{
    internal class NewOrderMessage : IMessage
    {
        private const string EventHubName = "neworder";

        private readonly bool _someOtherSetting;
        public NewOrderMessage(bool someOtherSetting)
        {
            _someOtherSetting = someOtherSetting;
        }

        public string GetEventHubName()
        {
            return EventHubName;
        }
    }
}

To get the event hub name printed via reflection we have use below code in a console app.

using System.Runtime.Serialization;

namespace getuntnitializeobject;

class Program
{
    static void Main(string[] args)
    {
        IReadOnlyList<Type> types = GetAssemblyTypes();

        IEnumerable<Type> messagesTypes = types
                .Where(t => typeof(IMessage).IsAssignableFrom(t)
                    && !t.IsInterface
                    && !t.IsAbstract);

        foreach (Type t in messagesTypes)
        {
            Console
          .WriteLine($"Type name: {t.FullName} Event hub name: {GetEventHubName(t)}");
        }
    }

    private static string GetEventHubName(Type e)
    {
        // this is obsolete
        IMessage messageInstace =
            (IMessage)FormatterServices.GetUninitializedObject(e);

        return messageInstace.GetEventHubName();
    }

    private static IReadOnlyList<Type> GetAssemblyTypes()
    {
        return AppDomain.CurrentDomain
            .GetAssemblies()
            .Select(t =>
            {
                try
                {
                    return t.GetTypes();
                }
                catch (Exception)
                {
                    return null;
                }
            })
            .Where(t => t != null)
            .SelectMany(t => t)
            .ToList();
    }
}

The code output is as shown below.


We can use RuntimeHelpers.GetUninitializedObject instead of FormatterServices.GetUninitializedObject  as shown below to achive the same results.

using System.Runtime.CompilerServices;
//using System.Runtime.Serialization;

namespace getuntnitializeobject;

class Program
{
    static void Main(string[] args)
    {
        IReadOnlyList<Type> types = GetAssemblyTypes();

        IEnumerable<Type> messagesTypes = types
                .Where(t => typeof(IMessage).IsAssignableFrom(t)
                    && !t.IsInterface
                    && !t.IsAbstract);

        foreach (Type t in messagesTypes)
        {
            Console
          .WriteLine($"Type name: {t.FullName} Event hub name: {GetEventHubName(t)}");
        }
    }

    private static string GetEventHubName(Type e)
    {
        // this is obsolete
        //IMessage messageInstace =
        //    (IMessage)FormatterServices.GetUninitializedObject(e);

        // use below instead
        IMessage messageInstace =
          (IMessage)RuntimeHelpers.GetUninitializedObject(e);

        return messageInstace.GetEventHubName();

    }

    private static IReadOnlyList<Type> GetAssemblyTypes()
    {
        return AppDomain.CurrentDomain
            .GetAssemblies()
            .Select(t =>
            {
                try
                {
                    return t.GetTypes();
                }
                catch (Exception)
                {
                    return null;
                }
            })
            .Where(t => t != null)
            .SelectMany(t => t)
            .ToList();
    }
}


No comments:

Popular Posts