1

Using a PrivateObject, I'm trying to create an instance of the ItemChange class (found here). Looking through the debugger as well as the object browser in Visual Studio 2008 I can't seem to find anything related to the ItemId property other than a setter. Below is the code I am using.

var itemChange = new PrivateObject(typeof(ItemChange));

itemChange.SetFieldOrProperty("ChangeType", _fixture.CreateAnonymous<ChangeType>());
itemChange.SetFieldOrProperty("ItemId", _fixture.CreateAnonymous<ItemId>());

The error I receive is:

System.MissingMethodException : Method 'Microsoft.Exchange.WebServices.Data.ItemChange.ItemId' not found.

I've tried variations of BindingFlags, however nothing seems to help. How can I set a property that has no setter and only a getter?

Edit

Regarding my comments, the other inline class that I can create a PrivateObject object instance and set the ItemId is the ItemEvent class (found here). This class was easy because when I was debugging and added the class to my watch list I could see itemId as a private variable. However, performing the same steps on the ItemChange class I cannot find any traces of an ItemId field other than the property itself that only has a setter. This is where I'm stumped on how to set this property.

Lastly, I don't have access to a tool that would allow me to decompile the class and see what is what.

8
  • It's a little bit tricky and it can fail if you change the implementation but can you use Reflection? Commented Apr 13, 2012 at 13:42
  • I thought PrivateObject was a wrapper around all that reflection stuff, no? Commented Apr 13, 2012 at 13:43
  • You need to try and set the private variable, as it is you are trying to set the public one which is failing. Commented Apr 13, 2012 at 13:44
  • If you provide a property name it can't understand what's the backing store. Commented Apr 13, 2012 at 13:49
  • 1
    helpful hint: when digging into the guts of a class, don't stop until you hit object. Commented Apr 13, 2012 at 15:01

2 Answers 2

2

A public get-only property does not necessarily have private setter. If you have not authored the target class yourself, you will probably need to grab a decompiler like Reflector to figure out what you need to change in order to change the value returned by the property getter.

If you find yourself needing to do this sort of thing often, you might want to consider using an alternate approach to control the behaviour of third-party code without appropriate extension hooks. For example, Moles would allow you to substitute your own desired behaviour for the getter without knowing anything about the innards of the property or the class.

Sign up to request clarification or add additional context in comments.

Comments

1

If the property you are trying to set is read-only and not backed by any underlying private field, then you can't actually set it. For example, if you had the following property:

public string ItemId
{
  get 
  {
    return "Test";
  }
}

nothing you do is ever going to set this property to another value. If you don't see an obvious backing field when you look through the object's fields in the debugger and/or reflection, this is likely the situation.

In this case, if I had to make a guess, I would say that ItemId is probably a shortcut property that simply returns this.Item.Id.

EDIT:

I was partly true. According to dotPeek, ItemChange.ItemId just returns Change.id, appropriately typecast. If Change.serviceObject has a value, than Change.id returns Change.serviceObject.GetId(), otherwise it returns Change.id. Which of those is appropriate in your case depends on the kind of change you're talking about, per MSDN:

Item is null when the ChangeType property has a value of either ChangeType.Delete or ChangeType.ReadFlagChange.

Effectively, the implementation of Change and ItemChange does something like this:

public class Base 
{
  private Thing thing;
  private BaseId id;

  internal BaseId Id
  {
    get
    {
      return this.thing == null ? this.id : this.thing.GetId();
    }
  }
}

public class Child
{
  public ChildId ChildId
  {
    get 
    { 
      return (ChildId) this.Id; 
    }
  }
}

In the actual Change implementation, the object field is a ServiceObject named serviceObject, which has a GetId() method that returns a ServiceId, and there is also an id field of type ServiceId. To get your ItemChange object's ItemId property set, you need to set one or the other of those internal fields on the object's base class (the serviceObject field takes precedence if it's set.)

2 Comments

That makes total sense. I hadn't thought of that before. If it's not too much of a hassle, do you think you could post the code for ItemChange and Change that was received from dotPeek? Until I go through the proper channels to have dotPeek installed it'll be a few weeks. Thank you.
I am hesitant to post that code because it is Microsoft copyrighted code and not part of a publically released reference source. However, the implementation is simple, I will add in a similar example that should get you what you need.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.