views:

5436

answers:

6

In a C# program, I have an abstract base class with a static "Create" method. The Create method is used to create an instance of the class and store it locally for later use. Since the base class is abstract, implementation objects will always derive from it.

I want to be able to derive an object from the base class, call the static Create method (implemented once in the base class) through the derived class, and create an instance of the derived object.

Are there any facilities within the C# language that will allow me to pull this off. My current fallback position is to pass an instance of the derived class as one of the arguments to the Create function, i.e.:

objDerived.Create(new objDerived(), "Arg1", "Arg2");
+1  A: 

You can't do it without outside information; either the type of the derived class, an instance of it, or the fully-qualified name of the derived class. Any of these are equivalent to what you're already doing; there isn't a better solution I'm aware of. The very nature of static methods precludes anything more elegant.

technophile
+2  A: 

Sounds like you need to make the Create() method abstract. And once you do that you might as well rename it and make it the constructor as well. Then you can have a different Init() method that you call after the object is constructed if you need to, and normal polymorphism effects will handle things.

Joel Coehoorn
Static members can't be marked abstract, and non-static members are useless for this; if you can call new DerivedFoo(), then you clearly have no need for what the original post is asking for.
technophile
That was kinda the point.
Joel Coehoorn
+8  A: 

Try using generics:

public static BaseClass Create<T>() where T : BaseClass, new()
{
    T newVar = new T();
    // Do something with newVar
    return T;
}

Sample use:

DerivedClass d = BaseClass.Create<DerivedClass>();
chilltemp
+3  A: 

You want to create a new instance of derived from inside another instance of derived, using a static factory method on the abstract base class? if so, I wonder Why... But ...

 public abstract class MyBase
 {
    public static T GetNewDerived<T>() where T : MyBase, new()
    {
        return new T();
    }    
 }
 public class DerivedA : MyBase
 {
    public static DerivedA GetNewDerived()
    {
        return GetNewDerived<DerivedA>();
    }
 }

 public class DerivedB : MyBase
 {
    public static DerivedB GetNewDerived()
    {
        return GetNewDerived<DerivedB>();
    }
 }

Is this what you want ?

Charles Bretana
A: 

I'm not sure what your design goals are but from what you asked it sounds like it might end up with alot of code smell. I think you should really look into the Inversion of Control(IoC) / Dependency Injection (DI) design patterns that are implemented in numerous frameworks such as Microsoft Unity, Castle Windsor, StructureMap, Ninject, Spring.Net and so forth.

I think if you look at using an IoC container it will solve your problem in a much cleaner and loosely coupled way.

Chris Marisic
+2  A: 

Summary

There are two main options. The nicer and newer one is to use generics, the other is to use reflection. I'm providing both in case you need to develop a solution that works prior to .NET 2.0.

Generics

abstract class BaseClass
{
  public static BaseClass Create<T>() where T : BaseClass, new()
  {
    return new T();
  }
}

Where the usage would be:

DerivedClass derivedInstance = BaseClass.Create<DerivedClass>();

Reflection

abstract class BaseClass
{
  public static BaseClass Create(Type derivedType)
  {
    // Cast will throw at runtime if the created class
    // doesn't derive from BaseClass.
    return (BaseClass)Activator.CreateInstance(derivedType);
  }
}

Where the usage would be (split over two lines for readability):

DerivedClass derivedClass
    = (DerivedClass)BaseClass.Create(typeof(DerivedClass));
Jeff Yates