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












4















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?










share|improve this question




















  • 2





    Mabe make the base method, accepting a generic type and then create instance from that. see stackoverflow.com/questions/731452/…

    – Malior
    Jan 3 at 10:28











  • But if dictionary will be static, then you will share the same dictionary over between A and B, which may be not what you want.

    – Michał Turczyn
    Jan 3 at 10:32













  • Is the constructor public visibility intended ?

    – Spotted
    Jan 3 at 10:45











  • Why do you want to limit the number of instance based on instanceName ? Is it allowed that both an instance of A and an instance of B with the same instanceName ?

    – Spotted
    Jan 3 at 11:06











  • Name can be a part of base class/interface. As for GetX you can't avoid declaration of it, unless you can make it generic, then base class is where it should normally be. You can still declare type specific static method to invoke that generic method for the comfort of those type users.

    – Sinatr
    Jan 3 at 11:11
















4















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?










share|improve this question




















  • 2





    Mabe make the base method, accepting a generic type and then create instance from that. see stackoverflow.com/questions/731452/…

    – Malior
    Jan 3 at 10:28











  • But if dictionary will be static, then you will share the same dictionary over between A and B, which may be not what you want.

    – Michał Turczyn
    Jan 3 at 10:32













  • Is the constructor public visibility intended ?

    – Spotted
    Jan 3 at 10:45











  • Why do you want to limit the number of instance based on instanceName ? Is it allowed that both an instance of A and an instance of B with the same instanceName ?

    – Spotted
    Jan 3 at 11:06











  • Name can be a part of base class/interface. As for GetX you can't avoid declaration of it, unless you can make it generic, then base class is where it should normally be. You can still declare type specific static method to invoke that generic method for the comfort of those type users.

    – Sinatr
    Jan 3 at 11:11














4












4








4








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?










share|improve this question
















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?







c# inheritance code-duplication static-polymorphism






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 3 at 11:21









Wai Ha Lee

6,096124065




6,096124065










asked Jan 3 at 10:16









user7330525user7330525

309




309








  • 2





    Mabe make the base method, accepting a generic type and then create instance from that. see stackoverflow.com/questions/731452/…

    – Malior
    Jan 3 at 10:28











  • But if dictionary will be static, then you will share the same dictionary over between A and B, which may be not what you want.

    – Michał Turczyn
    Jan 3 at 10:32













  • Is the constructor public visibility intended ?

    – Spotted
    Jan 3 at 10:45











  • Why do you want to limit the number of instance based on instanceName ? Is it allowed that both an instance of A and an instance of B with the same instanceName ?

    – Spotted
    Jan 3 at 11:06











  • Name can be a part of base class/interface. As for GetX you can't avoid declaration of it, unless you can make it generic, then base class is where it should normally be. You can still declare type specific static method to invoke that generic method for the comfort of those type users.

    – Sinatr
    Jan 3 at 11:11














  • 2





    Mabe make the base method, accepting a generic type and then create instance from that. see stackoverflow.com/questions/731452/…

    – Malior
    Jan 3 at 10:28











  • But if dictionary will be static, then you will share the same dictionary over between A and B, which may be not what you want.

    – Michał Turczyn
    Jan 3 at 10:32













  • Is the constructor public visibility intended ?

    – Spotted
    Jan 3 at 10:45











  • Why do you want to limit the number of instance based on instanceName ? Is it allowed that both an instance of A and an instance of B with the same instanceName ?

    – Spotted
    Jan 3 at 11:06











  • Name can be a part of base class/interface. As for GetX you can't avoid declaration of it, unless you can make it generic, then base class is where it should normally be. You can still declare type specific static method to invoke that generic method for the comfort of those type users.

    – Sinatr
    Jan 3 at 11:11








2




2





Mabe make the base method, accepting a generic type and then create instance from that. see stackoverflow.com/questions/731452/…

– Malior
Jan 3 at 10:28





Mabe make the base method, accepting a generic type and then create instance from that. see stackoverflow.com/questions/731452/…

– Malior
Jan 3 at 10:28













But if dictionary will be static, then you will share the same dictionary over between A and B, which may be not what you want.

– Michał Turczyn
Jan 3 at 10:32







But if dictionary will be static, then you will share the same dictionary over between A and B, which may be not what you want.

– Michał Turczyn
Jan 3 at 10:32















Is the constructor public visibility intended ?

– Spotted
Jan 3 at 10:45





Is the constructor public visibility intended ?

– Spotted
Jan 3 at 10:45













Why do you want to limit the number of instance based on instanceName ? Is it allowed that both an instance of A and an instance of B with the same instanceName ?

– Spotted
Jan 3 at 11:06





Why do you want to limit the number of instance based on instanceName ? Is it allowed that both an instance of A and an instance of B with the same instanceName ?

– Spotted
Jan 3 at 11:06













Name can be a part of base class/interface. As for GetX you can't avoid declaration of it, unless you can make it generic, then base class is where it should normally be. You can still declare type specific static method to invoke that generic method for the comfort of those type users.

– Sinatr
Jan 3 at 11:11





Name can be a part of base class/interface. As for GetX you can't avoid declaration of it, unless you can make it generic, then base class is where it should normally be. You can still declare type specific static method to invoke that generic method for the comfort of those type users.

– Sinatr
Jan 3 at 11:11












4 Answers
4






active

oldest

votes


















2














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;
}
}
}





share|improve this answer


























  • You forgot to add to the Registry when you were creating a new instance. That way, it will never hit the dictionary.

    – Anderson Pimentel
    Jan 3 at 10:40








  • 1





    @AndersonPimentel, noticed as soon as I posted it. Thanks for noticing. Great answer btw.

    – John Babb
    Jan 3 at 10:47











  • Thanks @JohnBabb for that helpful approach.

    – user7330525
    Jan 3 at 12:03



















1














Are you looking for a generic base class?



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

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

public static T GetValue (string instanceName, Func<string, T> creator) {
lock (Registry)
{
if (!Registry.TryGetValue(instanceName, out var newInstance))
{
newInstance = creator(instanceName);
}
return newInstance;
}
}
}


And then use it like this:



public class A : BaseRegistryGetter<A>
{
public A(string name) : base(name)
{
}

public static A GetA(string instanceName)
{
return BaseRegistryGetter<A>.GetValue(instanceName, s => new A(s));
}
}


The source for the awkward approach to make sure there is a string-constructor for A can be found here.






share|improve this answer































    0














    I think this should work. You can adapt it to fit your needs. Also, there was a bug in your code: you forgot to add to the Registry when you were creating a new instance.



    class Program
    {
    static void Main(string args)
    {
    A a1 = A.GetInstance("a");
    A a2 = A.GetInstance("aa");
    A a3 = A.GetInstance("a");

    B b1 = B.GetInstance("a");
    B b2 = B.GetInstance("aa");
    B b3 = B.GetInstance("a");

    Console.WriteLine(a1 == a2); //false
    Console.WriteLine(a1 == a3); //true

    Console.WriteLine(b1 == b2); //false
    Console.WriteLine(b1 == b3); //true

    Console.ReadKey();
    }
    }

    public class A : Generic<A>
    {
    public A(string name)
    : base(name)
    {
    }
    }

    public class B : Generic<B>
    {
    public B(string name)
    : base(name)
    {
    }
    }

    public abstract class Generic<T> where T : Generic<T>
    {
    private static readonly IDictionary<string, T> Registry = new Dictionary<string, T>();
    public string Name { get; set; }

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

    public static T GetInstance(string instanceName)
    {
    lock (Registry)
    {
    if (!Registry.TryGetValue(instanceName, out var newInstance))
    {
    newInstance = (T)Activator.CreateInstance(typeof(T), instanceName);
    Registry.Add(instanceName, newInstance);
    }
    return newInstance;
    }
    }
    }





    share|improve this answer































      0














      All the other answers try to solve this with generics, but it might be the case you wouldn't want to do this. First, it could be an unnecessary restriction further along that could end up causing variance issues. Second, it only solves one level of inheritance, if there is more, you are stuck again with the same problem:



       class Base<T> { ... }
      class A: Base<A> { ... }
      class B: A { //How does the generic base class help? }


      There are general solutions without the use generics that entails just a little code duplication. One could be the following:



      public class Base
      {
      static readonly IDictionary<string, Base> Registry =
      new Dictionary<string, Base>();

      protected static Base GetBase(string instanceName,
      Func<Base> creator)
      {
      lock (Registry)
      {
      if (!Registry.TryGetValue(instanceName, out var newInstance))
      {
      newInstance = creator();
      }

      return newInstance;
      }
      }

      //...
      }


      And now yor derived types can impement a strongly typed delegated method:



      public class A: Base
      {
      public A(string instanceName)
      :base(instanceName)
      {
      }
      public static A GetA(string instanceName)
      => GetBase(instanceName, () => new A(instanceName)) as A;
      }

      public class B: Base
      {
      public B(string instanceName)
      :base(instanceName)
      {
      }
      public static B GetB(string instanceName)
      => GetBase(instanceName, () => new B(instanceName)) as B;
      }





      share|improve this answer


























      • Did you forget to add to Registry in your first code sample? Could Registry instead be a ConcurrentDictionary (perhaps where the value is Lazy)?

        – mjwills
        Jan 3 at 11:08











      • @sinatr Sorry about the mess, I really need to go to bed. This is more or less what I had in mind. And yes, another option is making Register generic and calling Activator.CreateInstance but that relies on reflection...

        – InBetween
        Jan 3 at 11:45











      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54020243%2fhow-can-i-avoid-code-duplication-of-a-static-method-in-multiple-classes%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      4 Answers
      4






      active

      oldest

      votes








      4 Answers
      4






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      2














      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;
      }
      }
      }





      share|improve this answer


























      • You forgot to add to the Registry when you were creating a new instance. That way, it will never hit the dictionary.

        – Anderson Pimentel
        Jan 3 at 10:40








      • 1





        @AndersonPimentel, noticed as soon as I posted it. Thanks for noticing. Great answer btw.

        – John Babb
        Jan 3 at 10:47











      • Thanks @JohnBabb for that helpful approach.

        – user7330525
        Jan 3 at 12:03
















      2














      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;
      }
      }
      }





      share|improve this answer


























      • You forgot to add to the Registry when you were creating a new instance. That way, it will never hit the dictionary.

        – Anderson Pimentel
        Jan 3 at 10:40








      • 1





        @AndersonPimentel, noticed as soon as I posted it. Thanks for noticing. Great answer btw.

        – John Babb
        Jan 3 at 10:47











      • Thanks @JohnBabb for that helpful approach.

        – user7330525
        Jan 3 at 12:03














      2












      2








      2







      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;
      }
      }
      }





      share|improve this answer















      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;
      }
      }
      }






      share|improve this answer














      share|improve this answer



      share|improve this answer








      edited Jan 3 at 10:41

























      answered Jan 3 at 10:38









      John BabbJohn Babb

      8771018




      8771018













      • You forgot to add to the Registry when you were creating a new instance. That way, it will never hit the dictionary.

        – Anderson Pimentel
        Jan 3 at 10:40








      • 1





        @AndersonPimentel, noticed as soon as I posted it. Thanks for noticing. Great answer btw.

        – John Babb
        Jan 3 at 10:47











      • Thanks @JohnBabb for that helpful approach.

        – user7330525
        Jan 3 at 12:03



















      • You forgot to add to the Registry when you were creating a new instance. That way, it will never hit the dictionary.

        – Anderson Pimentel
        Jan 3 at 10:40








      • 1





        @AndersonPimentel, noticed as soon as I posted it. Thanks for noticing. Great answer btw.

        – John Babb
        Jan 3 at 10:47











      • Thanks @JohnBabb for that helpful approach.

        – user7330525
        Jan 3 at 12:03

















      You forgot to add to the Registry when you were creating a new instance. That way, it will never hit the dictionary.

      – Anderson Pimentel
      Jan 3 at 10:40







      You forgot to add to the Registry when you were creating a new instance. That way, it will never hit the dictionary.

      – Anderson Pimentel
      Jan 3 at 10:40






      1




      1





      @AndersonPimentel, noticed as soon as I posted it. Thanks for noticing. Great answer btw.

      – John Babb
      Jan 3 at 10:47





      @AndersonPimentel, noticed as soon as I posted it. Thanks for noticing. Great answer btw.

      – John Babb
      Jan 3 at 10:47













      Thanks @JohnBabb for that helpful approach.

      – user7330525
      Jan 3 at 12:03





      Thanks @JohnBabb for that helpful approach.

      – user7330525
      Jan 3 at 12:03













      1














      Are you looking for a generic base class?



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

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

      public static T GetValue (string instanceName, Func<string, T> creator) {
      lock (Registry)
      {
      if (!Registry.TryGetValue(instanceName, out var newInstance))
      {
      newInstance = creator(instanceName);
      }
      return newInstance;
      }
      }
      }


      And then use it like this:



      public class A : BaseRegistryGetter<A>
      {
      public A(string name) : base(name)
      {
      }

      public static A GetA(string instanceName)
      {
      return BaseRegistryGetter<A>.GetValue(instanceName, s => new A(s));
      }
      }


      The source for the awkward approach to make sure there is a string-constructor for A can be found here.






      share|improve this answer




























        1














        Are you looking for a generic base class?



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

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

        public static T GetValue (string instanceName, Func<string, T> creator) {
        lock (Registry)
        {
        if (!Registry.TryGetValue(instanceName, out var newInstance))
        {
        newInstance = creator(instanceName);
        }
        return newInstance;
        }
        }
        }


        And then use it like this:



        public class A : BaseRegistryGetter<A>
        {
        public A(string name) : base(name)
        {
        }

        public static A GetA(string instanceName)
        {
        return BaseRegistryGetter<A>.GetValue(instanceName, s => new A(s));
        }
        }


        The source for the awkward approach to make sure there is a string-constructor for A can be found here.






        share|improve this answer


























          1












          1








          1







          Are you looking for a generic base class?



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

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

          public static T GetValue (string instanceName, Func<string, T> creator) {
          lock (Registry)
          {
          if (!Registry.TryGetValue(instanceName, out var newInstance))
          {
          newInstance = creator(instanceName);
          }
          return newInstance;
          }
          }
          }


          And then use it like this:



          public class A : BaseRegistryGetter<A>
          {
          public A(string name) : base(name)
          {
          }

          public static A GetA(string instanceName)
          {
          return BaseRegistryGetter<A>.GetValue(instanceName, s => new A(s));
          }
          }


          The source for the awkward approach to make sure there is a string-constructor for A can be found here.






          share|improve this answer













          Are you looking for a generic base class?



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

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

          public static T GetValue (string instanceName, Func<string, T> creator) {
          lock (Registry)
          {
          if (!Registry.TryGetValue(instanceName, out var newInstance))
          {
          newInstance = creator(instanceName);
          }
          return newInstance;
          }
          }
          }


          And then use it like this:



          public class A : BaseRegistryGetter<A>
          {
          public A(string name) : base(name)
          {
          }

          public static A GetA(string instanceName)
          {
          return BaseRegistryGetter<A>.GetValue(instanceName, s => new A(s));
          }
          }


          The source for the awkward approach to make sure there is a string-constructor for A can be found here.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Jan 3 at 10:31









          CompufreakCompufreak

          2,12711130




          2,12711130























              0














              I think this should work. You can adapt it to fit your needs. Also, there was a bug in your code: you forgot to add to the Registry when you were creating a new instance.



              class Program
              {
              static void Main(string args)
              {
              A a1 = A.GetInstance("a");
              A a2 = A.GetInstance("aa");
              A a3 = A.GetInstance("a");

              B b1 = B.GetInstance("a");
              B b2 = B.GetInstance("aa");
              B b3 = B.GetInstance("a");

              Console.WriteLine(a1 == a2); //false
              Console.WriteLine(a1 == a3); //true

              Console.WriteLine(b1 == b2); //false
              Console.WriteLine(b1 == b3); //true

              Console.ReadKey();
              }
              }

              public class A : Generic<A>
              {
              public A(string name)
              : base(name)
              {
              }
              }

              public class B : Generic<B>
              {
              public B(string name)
              : base(name)
              {
              }
              }

              public abstract class Generic<T> where T : Generic<T>
              {
              private static readonly IDictionary<string, T> Registry = new Dictionary<string, T>();
              public string Name { get; set; }

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

              public static T GetInstance(string instanceName)
              {
              lock (Registry)
              {
              if (!Registry.TryGetValue(instanceName, out var newInstance))
              {
              newInstance = (T)Activator.CreateInstance(typeof(T), instanceName);
              Registry.Add(instanceName, newInstance);
              }
              return newInstance;
              }
              }
              }





              share|improve this answer




























                0














                I think this should work. You can adapt it to fit your needs. Also, there was a bug in your code: you forgot to add to the Registry when you were creating a new instance.



                class Program
                {
                static void Main(string args)
                {
                A a1 = A.GetInstance("a");
                A a2 = A.GetInstance("aa");
                A a3 = A.GetInstance("a");

                B b1 = B.GetInstance("a");
                B b2 = B.GetInstance("aa");
                B b3 = B.GetInstance("a");

                Console.WriteLine(a1 == a2); //false
                Console.WriteLine(a1 == a3); //true

                Console.WriteLine(b1 == b2); //false
                Console.WriteLine(b1 == b3); //true

                Console.ReadKey();
                }
                }

                public class A : Generic<A>
                {
                public A(string name)
                : base(name)
                {
                }
                }

                public class B : Generic<B>
                {
                public B(string name)
                : base(name)
                {
                }
                }

                public abstract class Generic<T> where T : Generic<T>
                {
                private static readonly IDictionary<string, T> Registry = new Dictionary<string, T>();
                public string Name { get; set; }

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

                public static T GetInstance(string instanceName)
                {
                lock (Registry)
                {
                if (!Registry.TryGetValue(instanceName, out var newInstance))
                {
                newInstance = (T)Activator.CreateInstance(typeof(T), instanceName);
                Registry.Add(instanceName, newInstance);
                }
                return newInstance;
                }
                }
                }





                share|improve this answer


























                  0












                  0








                  0







                  I think this should work. You can adapt it to fit your needs. Also, there was a bug in your code: you forgot to add to the Registry when you were creating a new instance.



                  class Program
                  {
                  static void Main(string args)
                  {
                  A a1 = A.GetInstance("a");
                  A a2 = A.GetInstance("aa");
                  A a3 = A.GetInstance("a");

                  B b1 = B.GetInstance("a");
                  B b2 = B.GetInstance("aa");
                  B b3 = B.GetInstance("a");

                  Console.WriteLine(a1 == a2); //false
                  Console.WriteLine(a1 == a3); //true

                  Console.WriteLine(b1 == b2); //false
                  Console.WriteLine(b1 == b3); //true

                  Console.ReadKey();
                  }
                  }

                  public class A : Generic<A>
                  {
                  public A(string name)
                  : base(name)
                  {
                  }
                  }

                  public class B : Generic<B>
                  {
                  public B(string name)
                  : base(name)
                  {
                  }
                  }

                  public abstract class Generic<T> where T : Generic<T>
                  {
                  private static readonly IDictionary<string, T> Registry = new Dictionary<string, T>();
                  public string Name { get; set; }

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

                  public static T GetInstance(string instanceName)
                  {
                  lock (Registry)
                  {
                  if (!Registry.TryGetValue(instanceName, out var newInstance))
                  {
                  newInstance = (T)Activator.CreateInstance(typeof(T), instanceName);
                  Registry.Add(instanceName, newInstance);
                  }
                  return newInstance;
                  }
                  }
                  }





                  share|improve this answer













                  I think this should work. You can adapt it to fit your needs. Also, there was a bug in your code: you forgot to add to the Registry when you were creating a new instance.



                  class Program
                  {
                  static void Main(string args)
                  {
                  A a1 = A.GetInstance("a");
                  A a2 = A.GetInstance("aa");
                  A a3 = A.GetInstance("a");

                  B b1 = B.GetInstance("a");
                  B b2 = B.GetInstance("aa");
                  B b3 = B.GetInstance("a");

                  Console.WriteLine(a1 == a2); //false
                  Console.WriteLine(a1 == a3); //true

                  Console.WriteLine(b1 == b2); //false
                  Console.WriteLine(b1 == b3); //true

                  Console.ReadKey();
                  }
                  }

                  public class A : Generic<A>
                  {
                  public A(string name)
                  : base(name)
                  {
                  }
                  }

                  public class B : Generic<B>
                  {
                  public B(string name)
                  : base(name)
                  {
                  }
                  }

                  public abstract class Generic<T> where T : Generic<T>
                  {
                  private static readonly IDictionary<string, T> Registry = new Dictionary<string, T>();
                  public string Name { get; set; }

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

                  public static T GetInstance(string instanceName)
                  {
                  lock (Registry)
                  {
                  if (!Registry.TryGetValue(instanceName, out var newInstance))
                  {
                  newInstance = (T)Activator.CreateInstance(typeof(T), instanceName);
                  Registry.Add(instanceName, newInstance);
                  }
                  return newInstance;
                  }
                  }
                  }






                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Jan 3 at 10:37









                  Anderson PimentelAnderson Pimentel

                  3,73122245




                  3,73122245























                      0














                      All the other answers try to solve this with generics, but it might be the case you wouldn't want to do this. First, it could be an unnecessary restriction further along that could end up causing variance issues. Second, it only solves one level of inheritance, if there is more, you are stuck again with the same problem:



                       class Base<T> { ... }
                      class A: Base<A> { ... }
                      class B: A { //How does the generic base class help? }


                      There are general solutions without the use generics that entails just a little code duplication. One could be the following:



                      public class Base
                      {
                      static readonly IDictionary<string, Base> Registry =
                      new Dictionary<string, Base>();

                      protected static Base GetBase(string instanceName,
                      Func<Base> creator)
                      {
                      lock (Registry)
                      {
                      if (!Registry.TryGetValue(instanceName, out var newInstance))
                      {
                      newInstance = creator();
                      }

                      return newInstance;
                      }
                      }

                      //...
                      }


                      And now yor derived types can impement a strongly typed delegated method:



                      public class A: Base
                      {
                      public A(string instanceName)
                      :base(instanceName)
                      {
                      }
                      public static A GetA(string instanceName)
                      => GetBase(instanceName, () => new A(instanceName)) as A;
                      }

                      public class B: Base
                      {
                      public B(string instanceName)
                      :base(instanceName)
                      {
                      }
                      public static B GetB(string instanceName)
                      => GetBase(instanceName, () => new B(instanceName)) as B;
                      }





                      share|improve this answer


























                      • Did you forget to add to Registry in your first code sample? Could Registry instead be a ConcurrentDictionary (perhaps where the value is Lazy)?

                        – mjwills
                        Jan 3 at 11:08











                      • @sinatr Sorry about the mess, I really need to go to bed. This is more or less what I had in mind. And yes, another option is making Register generic and calling Activator.CreateInstance but that relies on reflection...

                        – InBetween
                        Jan 3 at 11:45
















                      0














                      All the other answers try to solve this with generics, but it might be the case you wouldn't want to do this. First, it could be an unnecessary restriction further along that could end up causing variance issues. Second, it only solves one level of inheritance, if there is more, you are stuck again with the same problem:



                       class Base<T> { ... }
                      class A: Base<A> { ... }
                      class B: A { //How does the generic base class help? }


                      There are general solutions without the use generics that entails just a little code duplication. One could be the following:



                      public class Base
                      {
                      static readonly IDictionary<string, Base> Registry =
                      new Dictionary<string, Base>();

                      protected static Base GetBase(string instanceName,
                      Func<Base> creator)
                      {
                      lock (Registry)
                      {
                      if (!Registry.TryGetValue(instanceName, out var newInstance))
                      {
                      newInstance = creator();
                      }

                      return newInstance;
                      }
                      }

                      //...
                      }


                      And now yor derived types can impement a strongly typed delegated method:



                      public class A: Base
                      {
                      public A(string instanceName)
                      :base(instanceName)
                      {
                      }
                      public static A GetA(string instanceName)
                      => GetBase(instanceName, () => new A(instanceName)) as A;
                      }

                      public class B: Base
                      {
                      public B(string instanceName)
                      :base(instanceName)
                      {
                      }
                      public static B GetB(string instanceName)
                      => GetBase(instanceName, () => new B(instanceName)) as B;
                      }





                      share|improve this answer


























                      • Did you forget to add to Registry in your first code sample? Could Registry instead be a ConcurrentDictionary (perhaps where the value is Lazy)?

                        – mjwills
                        Jan 3 at 11:08











                      • @sinatr Sorry about the mess, I really need to go to bed. This is more or less what I had in mind. And yes, another option is making Register generic and calling Activator.CreateInstance but that relies on reflection...

                        – InBetween
                        Jan 3 at 11:45














                      0












                      0








                      0







                      All the other answers try to solve this with generics, but it might be the case you wouldn't want to do this. First, it could be an unnecessary restriction further along that could end up causing variance issues. Second, it only solves one level of inheritance, if there is more, you are stuck again with the same problem:



                       class Base<T> { ... }
                      class A: Base<A> { ... }
                      class B: A { //How does the generic base class help? }


                      There are general solutions without the use generics that entails just a little code duplication. One could be the following:



                      public class Base
                      {
                      static readonly IDictionary<string, Base> Registry =
                      new Dictionary<string, Base>();

                      protected static Base GetBase(string instanceName,
                      Func<Base> creator)
                      {
                      lock (Registry)
                      {
                      if (!Registry.TryGetValue(instanceName, out var newInstance))
                      {
                      newInstance = creator();
                      }

                      return newInstance;
                      }
                      }

                      //...
                      }


                      And now yor derived types can impement a strongly typed delegated method:



                      public class A: Base
                      {
                      public A(string instanceName)
                      :base(instanceName)
                      {
                      }
                      public static A GetA(string instanceName)
                      => GetBase(instanceName, () => new A(instanceName)) as A;
                      }

                      public class B: Base
                      {
                      public B(string instanceName)
                      :base(instanceName)
                      {
                      }
                      public static B GetB(string instanceName)
                      => GetBase(instanceName, () => new B(instanceName)) as B;
                      }





                      share|improve this answer















                      All the other answers try to solve this with generics, but it might be the case you wouldn't want to do this. First, it could be an unnecessary restriction further along that could end up causing variance issues. Second, it only solves one level of inheritance, if there is more, you are stuck again with the same problem:



                       class Base<T> { ... }
                      class A: Base<A> { ... }
                      class B: A { //How does the generic base class help? }


                      There are general solutions without the use generics that entails just a little code duplication. One could be the following:



                      public class Base
                      {
                      static readonly IDictionary<string, Base> Registry =
                      new Dictionary<string, Base>();

                      protected static Base GetBase(string instanceName,
                      Func<Base> creator)
                      {
                      lock (Registry)
                      {
                      if (!Registry.TryGetValue(instanceName, out var newInstance))
                      {
                      newInstance = creator();
                      }

                      return newInstance;
                      }
                      }

                      //...
                      }


                      And now yor derived types can impement a strongly typed delegated method:



                      public class A: Base
                      {
                      public A(string instanceName)
                      :base(instanceName)
                      {
                      }
                      public static A GetA(string instanceName)
                      => GetBase(instanceName, () => new A(instanceName)) as A;
                      }

                      public class B: Base
                      {
                      public B(string instanceName)
                      :base(instanceName)
                      {
                      }
                      public static B GetB(string instanceName)
                      => GetBase(instanceName, () => new B(instanceName)) as B;
                      }






                      share|improve this answer














                      share|improve this answer



                      share|improve this answer








                      edited Jan 3 at 11:40

























                      answered Jan 3 at 11:00









                      InBetweenInBetween

                      25.4k34068




                      25.4k34068













                      • Did you forget to add to Registry in your first code sample? Could Registry instead be a ConcurrentDictionary (perhaps where the value is Lazy)?

                        – mjwills
                        Jan 3 at 11:08











                      • @sinatr Sorry about the mess, I really need to go to bed. This is more or less what I had in mind. And yes, another option is making Register generic and calling Activator.CreateInstance but that relies on reflection...

                        – InBetween
                        Jan 3 at 11:45



















                      • Did you forget to add to Registry in your first code sample? Could Registry instead be a ConcurrentDictionary (perhaps where the value is Lazy)?

                        – mjwills
                        Jan 3 at 11:08











                      • @sinatr Sorry about the mess, I really need to go to bed. This is more or less what I had in mind. And yes, another option is making Register generic and calling Activator.CreateInstance but that relies on reflection...

                        – InBetween
                        Jan 3 at 11:45

















                      Did you forget to add to Registry in your first code sample? Could Registry instead be a ConcurrentDictionary (perhaps where the value is Lazy)?

                      – mjwills
                      Jan 3 at 11:08





                      Did you forget to add to Registry in your first code sample? Could Registry instead be a ConcurrentDictionary (perhaps where the value is Lazy)?

                      – mjwills
                      Jan 3 at 11:08













                      @sinatr Sorry about the mess, I really need to go to bed. This is more or less what I had in mind. And yes, another option is making Register generic and calling Activator.CreateInstance but that relies on reflection...

                      – InBetween
                      Jan 3 at 11:45





                      @sinatr Sorry about the mess, I really need to go to bed. This is more or less what I had in mind. And yes, another option is making Register generic and calling Activator.CreateInstance but that relies on reflection...

                      – InBetween
                      Jan 3 at 11:45


















                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54020243%2fhow-can-i-avoid-code-duplication-of-a-static-method-in-multiple-classes%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Monofisismo

                      Angular Downloading a file using contenturl with Basic Authentication

                      Olmecas