Search code examples
c#inheritancecode-duplicationstatic-polymorphism

How can I avoid code duplication of a static method in multiple classes


I have multiple classes containing duplicated code, especially members and most important a static method that will create a new instance of the class and returning this instance: either a previously created instance registered in a dictionary or a new instance by calling the constructor.

An interface is no option, because I have the static method. I tried to solve the problem by introducing a base class that implements this static method, but I can not find a way to create and return a spefific child class properly.

Below is a code example of the current situation with class A and class B showing duplicated code.

public class A
{
    private static readonly IDictionary<string, A> Registry = new Dictionary<string, A>();
    public string Name { get; set; }

    public A(string name)
    {
        this.Name = name;
    }

    public static A GetA(string instanceName)
    {
        lock (Registry)
        {
            if (!Registry.TryGetValue(instanceName, out var newInstance))
            {
                newInstance = new A(instanceName);
            }
            return newInstance;
        }
    }
}

And then in class B again there is a member Name and the GetX() Method.

public class B
{
    private static readonly IDictionary<string, B> Registry = new Dictionary<string, B>();
    public string Name { get; set; }

    public B(string name)
    {
        this.Name = name;
    }

    public static B GetB(string instanceName)
    {
        lock (Registry)
        {
            if (!Registry.TryGetValue(instanceName, out var newInstance))
            {
                newInstance = new B(instanceName);
            }
            return newInstance;
        }
    }
}

Is there a possibility to avoid this kind of code duplication by introducing a base class or any other way?


Solution

  • This might be a little cleaner:

    public class B: RegistryInstance<B>
    {
        public string Name { get; set; }
    
        public B(string name)
        {
            this.Name = name;
        }
    }
    
    public class A : RegistryInstance<A>
    {
        public string Name { get; set; }
    
        public A(string name)
        {
            this.Name = name;
        }
    }
    
    public abstract class RegistryInstance<T> where T:class
    {
        protected static readonly IDictionary<string, T> Registry = new Dictionary<string, T>();
    
        public static T GetInstance(string instanceName)
        {
            lock (Registry)
            {
                if (!Registry.TryGetValue(instanceName, out var newInstance))
                {
                    newInstance = (T)Activator.CreateInstance(typeof(T), new object[] { instanceName });
                    Registry.Add(instanceName, newInstance);
                }
                return newInstance;
            }
        }
    }