1

使用 a PrivateObject,我正在尝试创建ItemChange该类的实例(在此处找到)。查看调试器以及 Visual Studio 2008 中的对象浏览器,除了 setter 之外,我似乎找不到与该属性相关的任何内容。ItemId下面是我正在使用的代码。

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

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

我收到的错误是:

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

我尝试了 的变体BindingFlags,但似乎没有任何帮助。如何设置没有 setter 而只有 getter 的属性?

编辑

关于我的评论,我可以创建PrivateObject对象实例并设置的另一个内联类ItemIdItemEvent类(在此处找到)。这个类很简单,因为当我调试并将该类添加到我的监视列表中时,我可以将itemId其视为私有变量。但是,在类上执行相同的步骤时,除了只有一个 setter的属性本身之外,ItemChange找不到任何字段痕迹。这是我对如何设置此属性感到困惑的地方。ItemId

最后,我无法使用可以让我反编译类并查看什么是什么的工具。

4

2 回答 2

2

公共 get-only 属性不一定具有私有 setter。如果您还没有自己编写目标类,您可能需要使用像Reflector这样的反编译器来确定您需要更改的内容,以便更改属性 getter 返回的值。

如果您发现自己经常需要做这种事情,您可能需要考虑使用另一种方法来控制第三方代码的行为,而无需适当的扩展挂钩。例如,Moles将允许您在不了解属性或类的内部情况的情况下用自己想要的行为替换 getter。

于 2012-04-13T14:47:58.377 回答
1

如果您尝试设置的属性是只读的并且不受任何底层私有字段的支持,那么您实际上无法设置它。例如,如果您有以下属性:

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

您所做的任何事情都不会将此属性设置为另一个值。如果在调试器和/或反射中查看对象的字段时没有看到明显的支持字段,则很可能是这种情况。

在这种情况下,如果我不得不猜测,我会说 ItemId 可能是一个快捷方式属性,它只返回this.Item.Id.

编辑:

我部分是对的。根据 dotPeek,ItemChange.ItemId只需返回Change.id,适当地进行类型转换。如果Change.serviceObject有值,则Change.id返回Change.serviceObject.GetId(),否则返回Change.id。根据 MSDN,哪些适合您的情况取决于您正在谈论的更改类型:

当 ChangeType 属性的值为 ChangeType.Delete 或 ChangeType.ReadFlagChange 时,Item 为空。

实际上,Change 和 ItemChange 的实现是这样的:

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.)

于 2012-04-13T14:49:10.573 回答