Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. Other Discussions
  3. Clever Code
  4. append extra fields to existing objects

append extra fields to existing objects

Scheduled Pinned Locked Moved Clever Code
6 Posts 4 Posters 2 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • K Offline
    K Offline
    Kevin Drzycimski
    wrote on last edited by
    #1

    In our project, I needed the XmlReader to carry an object-bound List. Unfortunately this class is abstract and I didn't really want to implement to whole thing just with that extra field. So I used TypeDescriptor to add an additional Attribute to the XmlReader:

    XsdErrorListAttribute listAttrib = new XsdErrorListAttribute();
    XmlReader xreader = ...;
    TypeDescriptor.AddAttributes(xreader, listAttrib);

    The XsdErrorListAttribute was quite simple:

    class XsdErrorListAttribute : Attribute
    {
    internal XsdErrorListAttribute()
    {
    ErrorList = new List<XsdError>();
    }

        internal List<XsdError> ErrorList
        { get; set; }
    
        internal static XsdErrorListAttribute getFromObject(object o)
        {
            var result = from Attribute a in TypeDescriptor.GetAttributes(o)
                         where a.GetType() == typeof(XsdErrorListAttribute)
                         select a;
            
            if (result.Count() == 1)
                return (XsdErrorListAttribute)result.Single();
            else
                return null;
        }
    }
    

    The static method tried to extract the attribute from an object. At the position where the list should be retrieved simply:

    XsdErrorListAttribute attrib = XsdErrorListAttribute.getFromObject(tmp);
    attrib.Liste.Add(new XsdError(...)); //yes, assuming that it's != null ...
    

    You can even add attributes to whole classes, or just like this to give your objects an extra piece of information.

    D M M 3 Replies Last reply
    0
    • K Kevin Drzycimski

      In our project, I needed the XmlReader to carry an object-bound List. Unfortunately this class is abstract and I didn't really want to implement to whole thing just with that extra field. So I used TypeDescriptor to add an additional Attribute to the XmlReader:

      XsdErrorListAttribute listAttrib = new XsdErrorListAttribute();
      XmlReader xreader = ...;
      TypeDescriptor.AddAttributes(xreader, listAttrib);

      The XsdErrorListAttribute was quite simple:

      class XsdErrorListAttribute : Attribute
      {
      internal XsdErrorListAttribute()
      {
      ErrorList = new List<XsdError>();
      }

          internal List<XsdError> ErrorList
          { get; set; }
      
          internal static XsdErrorListAttribute getFromObject(object o)
          {
              var result = from Attribute a in TypeDescriptor.GetAttributes(o)
                           where a.GetType() == typeof(XsdErrorListAttribute)
                           select a;
              
              if (result.Count() == 1)
                  return (XsdErrorListAttribute)result.Single();
              else
                  return null;
          }
      }
      

      The static method tried to extract the attribute from an object. At the position where the list should be retrieved simply:

      XsdErrorListAttribute attrib = XsdErrorListAttribute.getFromObject(tmp);
      attrib.Liste.Add(new XsdError(...)); //yes, assuming that it's != null ...
      

      You can even add attributes to whole classes, or just like this to give your objects an extra piece of information.

      D Offline
      D Offline
      dojohansen
      wrote on last edited by
      #2

      Neat idea! You're paying a performance price though. How about generating a class that extends XmlReader but implements by wrapping an existing implementation? I believe one could build a small code-generating tool that would do so without a lot of work, and it neatly solves the problem here because the framework does provide implementations but only the abstract base type is public. Something like this:

      // This class is *generated* by your little tool.

      public class WrappedXmlReader : XmlReader
      {
      XmlReader implementation;

      public WrappedXmlReader(XmlReader implementation)
      {
          this.implementation = implementation;
      }
      
      
      #region "Implement" abstract XmlReader members by delegation
      
      public override int  AttributeCount
      {
          get { return implementation.AttributeCount; }
      }
      
      // ... 
      
      public void Close()
      {
          implementation.Close();
      }
      
      // ...
      #endregion
      

      }

      // Now you extend the wrapped reader as you now have a non-sealed concrete "implementation" to derive from.
      public class MyReader : WrappedXmlReader
      {
      public MyReader(Stream s): base(XmlReader.Create(s)) {}

      public MyReader(XmlReader r) : base(r) {}
      
      public string Foo { get; set; }
      
      public void Bar()
      {
          Debug.WriteLine("Hello world");
      }
      

      }

      K 1 Reply Last reply
      0
      • D dojohansen

        Neat idea! You're paying a performance price though. How about generating a class that extends XmlReader but implements by wrapping an existing implementation? I believe one could build a small code-generating tool that would do so without a lot of work, and it neatly solves the problem here because the framework does provide implementations but only the abstract base type is public. Something like this:

        // This class is *generated* by your little tool.

        public class WrappedXmlReader : XmlReader
        {
        XmlReader implementation;

        public WrappedXmlReader(XmlReader implementation)
        {
            this.implementation = implementation;
        }
        
        
        #region "Implement" abstract XmlReader members by delegation
        
        public override int  AttributeCount
        {
            get { return implementation.AttributeCount; }
        }
        
        // ... 
        
        public void Close()
        {
            implementation.Close();
        }
        
        // ...
        #endregion
        

        }

        // Now you extend the wrapped reader as you now have a non-sealed concrete "implementation" to derive from.
        public class MyReader : WrappedXmlReader
        {
        public MyReader(Stream s): base(XmlReader.Create(s)) {}

        public MyReader(XmlReader r) : base(r) {}
        
        public string Foo { get; set; }
        
        public void Bar()
        {
            Debug.WriteLine("Hello world");
        }
        

        }

        K Offline
        K Offline
        Kevin Drzycimski
        wrote on last edited by
        #3

        ah ok thats really good! i had the problem inheritating the XmlReader because i couldnt fill the abstract methods. a code generator is always a good idea. but well, we call the TypeDescriptor very less than 1%, sometimes only once per action (more than a million calls to the reader). like this, all the indirect function calls cost more. so it depends on usage which method to use.

        1 Reply Last reply
        0
        • K Kevin Drzycimski

          In our project, I needed the XmlReader to carry an object-bound List. Unfortunately this class is abstract and I didn't really want to implement to whole thing just with that extra field. So I used TypeDescriptor to add an additional Attribute to the XmlReader:

          XsdErrorListAttribute listAttrib = new XsdErrorListAttribute();
          XmlReader xreader = ...;
          TypeDescriptor.AddAttributes(xreader, listAttrib);

          The XsdErrorListAttribute was quite simple:

          class XsdErrorListAttribute : Attribute
          {
          internal XsdErrorListAttribute()
          {
          ErrorList = new List<XsdError>();
          }

              internal List<XsdError> ErrorList
              { get; set; }
          
              internal static XsdErrorListAttribute getFromObject(object o)
              {
                  var result = from Attribute a in TypeDescriptor.GetAttributes(o)
                               where a.GetType() == typeof(XsdErrorListAttribute)
                               select a;
                  
                  if (result.Count() == 1)
                      return (XsdErrorListAttribute)result.Single();
                  else
                      return null;
              }
          }
          

          The static method tried to extract the attribute from an object. At the position where the list should be retrieved simply:

          XsdErrorListAttribute attrib = XsdErrorListAttribute.getFromObject(tmp);
          attrib.Liste.Add(new XsdError(...)); //yes, assuming that it's != null ...
          

          You can even add attributes to whole classes, or just like this to give your objects an extra piece of information.

          M Offline
          M Offline
          Mark Hurd
          wrote on last edited by
          #4

          You could simplify the usage of this with some Extension methods. Regards, Mark Hurd, B.Sc.(Ma.) (Hons.)

          K 1 Reply Last reply
          0
          • M Mark Hurd

            You could simplify the usage of this with some Extension methods. Regards, Mark Hurd, B.Sc.(Ma.) (Hons.)

            K Offline
            K Offline
            Kevin Drzycimski
            wrote on last edited by
            #5

            well, no ;) a extension method in fact is only something like a static method:

            void doSomething(this String str, int i) { /*...*/ }

            String s;
            s.doSomething(5);

            becomes

            static void doSomething(String str, int i) { /*...*/ }

            String s;
            doSomething(s, 5);

            you can not access private or protected fields, and especially you can not append an extra field to an object.

            1 Reply Last reply
            0
            • K Kevin Drzycimski

              In our project, I needed the XmlReader to carry an object-bound List. Unfortunately this class is abstract and I didn't really want to implement to whole thing just with that extra field. So I used TypeDescriptor to add an additional Attribute to the XmlReader:

              XsdErrorListAttribute listAttrib = new XsdErrorListAttribute();
              XmlReader xreader = ...;
              TypeDescriptor.AddAttributes(xreader, listAttrib);

              The XsdErrorListAttribute was quite simple:

              class XsdErrorListAttribute : Attribute
              {
              internal XsdErrorListAttribute()
              {
              ErrorList = new List<XsdError>();
              }

                  internal List<XsdError> ErrorList
                  { get; set; }
              
                  internal static XsdErrorListAttribute getFromObject(object o)
                  {
                      var result = from Attribute a in TypeDescriptor.GetAttributes(o)
                                   where a.GetType() == typeof(XsdErrorListAttribute)
                                   select a;
                      
                      if (result.Count() == 1)
                          return (XsdErrorListAttribute)result.Single();
                      else
                          return null;
                  }
              }
              

              The static method tried to extract the attribute from an object. At the position where the list should be retrieved simply:

              XsdErrorListAttribute attrib = XsdErrorListAttribute.getFromObject(tmp);
              attrib.Liste.Add(new XsdError(...)); //yes, assuming that it's != null ...
              

              You can even add attributes to whole classes, or just like this to give your objects an extra piece of information.

              M Offline
              M Offline
              Mr PoorEnglish
              wrote on last edited by
              #6

              internal static XsdErrorListAttribute getFromObject(object o) {
              return TypeDescriptor.GetAttributes(o).OfType<XsdErrorListAttribute>().FirstOrDefault();
              }

              does the same, or am i wrong?

              1 Reply Last reply
              0
              Reply
              • Reply as topic
              Log in to reply
              • Oldest to Newest
              • Newest to Oldest
              • Most Votes


              • Login

              • Don't have an account? Register

              • Login or register to search.
              • First post
                Last post
              0
              • Categories
              • Recent
              • Tags
              • Popular
              • World
              • Users
              • Groups