Tutorial :How is it that the abstract class XmlWriter can be instantiated using XmlWriter.Create(…?



Question:

Just looking to clarify my understanding of the workings of the XmlWriter and abstract classes in general.

My thinking is (was) that an abstract class can not be instantiated, although it can contain base methods that can be used by an inheriting class.

So, while investigating XmlWriter, I find that to instantiate the XmlWriter, you call XmlWriter.Create(.... , which returns an instance of... XmlWriter, which can then be used:

FileStream fs = new FileStream("XML.xml", FileMode.Create);    XmlWriter w = XmlWriter.Create(fs);    XmlSerializer xmlSlr = new XmlSerializer(typeof(TestClass));    xmlSlr.Serialize(fs, tsIn);  

This clearly works, as tested. Can anyone help me understand what is going on here. As far as I can see there is or should be no 'instance' to work with here??


Solution:1

You can't create an instance using new, but Create as it is used here is what is called a static factory method; it is NOT a constructor. You will find that in fact, the object returned by Create does not belong to abstract class XmlWriter, but some other concrete subclass.

See also


Solution:2

There's nothing abstract about the object you get back. There are 13 classes inside the .NET framework that implement XmlWriter. They are all internal, you could only see their names if you'd peek at the source code with Reflector.

Not having to know the names of those 13 classes yourself is very valuable both to you and Microsoft. To you because you don't have to learn the details of picking the right one. To Microsoft because they can completely change the implementation, even the name, of those classes and your code would never notice.

This is called the Factory Pattern.


Solution:3

This is what is known as the factory pattern.

In this case the abstract class also acts as the factory responsible for creating concrete instances of classes that extend itself.

This way the responsibility for creating the correct class is handed over to the factory, quite often the factory will make decisions on what class to create depending on some parameters you pass in or other things such as config/environment etc..


Solution:4

Thanks. Once I did a test on the type of the returned object, I got a type which derives from XmlWriter. What was confusing me, was that I didn't expect the abstract base class to be able to reference subclasses of it's self.

.NET must determine the type of concrete XmlWriter to return based on the input arguments.

The XmlWriter seems (to me) to work a little less intuitively than other implementations I have seen since reading all the comments here. Examples such as in the link below use the Create method from concrete classes.

http://www.codeproject.com/KB/architecture/CSharpClassFactory.aspx

I knocked out some code here to prove to my self that implementing the functionality via the Create method on the abstract class was possible. The create method of the abstract class can indeed reference derived types as shown here:

  using System;      using System.Collections.Generic;      using System.Linq;      using System.Text;        namespace TestFactoryPattern      {          public abstract class Input          {              public int Val;          }            public class InputObjA : Input          {              public InputObjA()              {                  Val = 1;              }          }            public class InputObjB : Input          {              public InputObjB()              {                  Val = 2;              }          }            public abstract class MyXmlWriter          {              public static int InputVal;                public static MyXmlWriter Create(Input input)              {                  InputVal = input.Val;                    if (input is InputObjA)                  {                      return new MyObjAXmlWriter();                  }                  else if (input is InputObjB)                  {                      return new MyObjBXmlWriter();                  }                  else                  {                      return new MyObjAXmlWriter();                  }              }                public abstract void WriteMyXml();          }            public class MyObjAXmlWriter : MyXmlWriter          {              public override void WriteMyXml()              {                  Console.WriteLine("Input A Written: " + InputVal);              }          }            public class MyObjBXmlWriter : MyXmlWriter          {              public override void WriteMyXml()              {                  Console.WriteLine("Input B Written: " + InputVal);              }          }            public class Program          {              public static void Main()              {                  InputObjA a = new InputObjA();                    MyXmlWriter myXml1 = MyXmlWriter.Create(a);                    myXml1.WriteMyXml();                    InputObjB b = new InputObjB();                    MyXmlWriter myXml2 = MyXmlWriter.Create(b);                    myXml2.WriteMyXml();                }        }  }  

Thanks all for the answers and input.


Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »