0

How could I create a subclass from this?

I want to add some methods to this class, but when I try to create a subclass I get this error:

Error   CS1729  'Item' does not contain a constructor that takes 0 arguments

Here is the code I wrote ( most of it is auto-generated ):

    using Microsoft.Exchange.WebServices.Data;

    public class ItemEx : Item
    {
        public override bool IsNew => base.IsNew;

        public override bool Equals(object obj)
        {
            return base.Equals(obj);
        }

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        public override string ToString()
        {
            return base.Subject;
            //return base.ToString();
        }
    }

This basic code gives error. Also as far as I know there is no constructor for the Item so what does c# really want?

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
Plato
  • 89
  • 1
  • 11
  • Why do you need to inherit from `Item` in the first place? – Salah Akbari Nov 29 '18 at 13:57
  • As you know every Item is a mail or contact or calendar item etc.. I want to put them in a comboBox in its entirety and want it to show the Subject as comboBox text ( via creating a ToString method with the code above ).. When the comboBox is selected I want to show the other properties in another control.. It is possible to store it elsewhere and later access it by some index, but this would have been easiest.. – Plato Nov 29 '18 at 17:45
  • @Plato, you could use extension methods, as proposed on the answers on the link I've put on my answer. – Pedro Gaspar Nov 29 '18 at 19:39
  • @Plato, does my response answer your original question? – Pedro Gaspar Dec 01 '18 at 15:07
  • I think extension methods will cover what I want to do.. So it's ok.. – Plato Dec 01 '18 at 15:10
  • It seems it's not ok because of this: https://stackoverflow.com/questions/4982479/how-to-create-an-extension-method-for-tostring – Plato Dec 04 '18 at 09:25

2 Answers2

2

If we take a look at the documentation (or here), it really doesn't show any constructors for the type Microsoft.Exchange.WebServices.Data.Item, but, if you take a look at all the types inherited from Item, they all implement the following constructor:

public InheritedFromItem(
    ExchangeService service
)

So I would guess that maybe you should implement it too.
Just confirmed looking the source code of Item type:

ews-managed-api/Item.cs at master · OfficeDev/ews-managed-api - GitHub https://github.com/OfficeDev/ews-managed-api/blob/master/Core/ServiceObjects/Items/Item.cs

namespace Microsoft.Exchange.WebServices.Data
{
    using System;
    using System.Collections.Generic;
    using System.Linq;

    /// <summary>
    /// Represents a generic item. Properties available on items are defined in the ItemSchema class.
    /// </summary>
    [Attachable]
    [ServiceObjectDefinition(XmlElementNames.Item)]
    public class Item : ServiceObject
    {
        private ItemAttachment parentAttachment;

        /// <summary>
        /// Initializes an unsaved local instance of <see cref="Item"/>. To bind to an existing item, use Item.Bind() instead.
        /// </summary>
        /// <param name="service">The ExchangeService object to which the item will be bound.</param>
        internal Item(ExchangeService service)
            : base(service)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Item"/> class.
        /// </summary>
        /// <param name="parentAttachment">The parent attachment.</param>
        internal Item(ItemAttachment parentAttachment)
            : this(parentAttachment.Service)
        {
            // [...]
        }

        // [...]

See that it actually has two internal constructors, one receiving an ExchangeService object and the other an ItemAttachment object.

Taking a look in Contact, that inherits from Item, as an example, it implements the ExchangeService constructor as public and the ItemAttachment constructor as internal:

ews-managed-api/Contact.cs at master · OfficeDev/ews-managed-api - GitHub
https://github.com/OfficeDev/ews-managed-api/blob/master/Core/ServiceObjects/Items/Contact.cs

namespace Microsoft.Exchange.WebServices.Data
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Text;

    /// <summary>
    /// Represents a contact. Properties available on contacts are defined in the ContactSchema class.
    /// </summary>
    [Attachable]
    [ServiceObjectDefinition(XmlElementNames.Contact)]
    public class Contact : Item
    {
        private const string ContactPictureName = "ContactPicture.jpg";

        /// <summary>
        /// Initializes an unsaved local instance of <see cref="Contact"/>. To bind to an existing contact, use Contact.Bind() instead.
        /// </summary>
        /// <param name="service">The ExchangeService object to which the contact will be bound.</param>
        public Contact(ExchangeService service)
            : base(service)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Contact"/> class.
        /// </summary>
        /// <param name="parentAttachment">The parent attachment.</param>
        internal Contact(ItemAttachment parentAttachment)
            : base(parentAttachment)
        {
        }

        // [...]

So, try to mimic that on your code:

using Microsoft.Exchange.WebServices.Data;

public class ItemEx : Item
{
    public ItemEx(ExchangeService service)
        : base(service)
    {
    }

    internal ItemEx(ItemAttachment parentAttachment)
        : base(parentAttachment)
    {
    }
}

But then you cannot instantiate an object of your class like this:

ItemEx myItem = new ItemEx();

You should do it like this:

ExchangeService service = new ExchangeService();
ItemEx myItem = new ItemEx(service);

UPDATE

Sorry for my previous ignorance. The internal access modifier on the constructors of Item class makes them accessible only within files in the same assembly.

So, that means that this Item class cannot be subclassed / inherited from others, outside Microsoft.Exchange.WebServices.dll assembly. Some reference:

Pedro Gaspar
  • 777
  • 8
  • 35
0

While not a perfect solution, it seems there is no way to extend a class with ToString method because they generally already have this method implemented on them.

Another solution would be using it like this:

class MailData
{
    public string subject;
    public Item mailItem;

    public MailData(string subject, Item mailItem)
    {
        this.subject = subject;
        this.mailItem = mailItem;
    }

    public override string ToString() => subject;

}

With this it's possible to use it like this:

        if (findResults.Items.Count > 0)
        {
            foreach (Item item in findResults.Items)
                comboBox1.Items.Add(new MailData(item.Subject,item));
        }

and use it like this later:

                    EmailMessage item = (selectedItem as MailData).mailItem as EmailMessage;
                    textBox1.Text = $"From: {item.From.Address}";
                    wb.DocumentText = item.Body.Text;
                    wb.Update();

Yes, it's a little bit convoluted and not actually what I wanted but it serves its' purpose.

PS: I use item for other purposes also, but here I'm using it for email..

Plato
  • 89
  • 1
  • 11
  • 2
    This response doesn't answer the original question: **How can I subclass `Microsoft.Exchange.WebServices.Data.Item`?** The answer to the original question is: **You can't**. You ended up changing the goal of the question (based on my answer?). When this happens (another question arises, based on the answers), you should create another question, since it's... another question. – Pedro Gaspar Dec 05 '18 at 19:32