Outlook Interop: How to iterate over all items in folder - c#

I would like to search the bodies of all outlook items. I know how to do this for the four PIM items (Notes/Tasks/Appointments/Contacts). But the code is identical for all of them with the exception of casting the COM object to the specific item type (i.e., ContactItem, AppointmentItem, etc). Is there a parent class for these PIM items, so that I can do something like this in my loop:
using Outlook = Microsoft.Office.Interop.Outlook
List SearchFolderItems( Outlook.Folder folder )
{
List results = new List();
foreach( object folderItem in folder.Items )
{
//GenericPIMItem is what I am wishing for
Outlook.GenericPIMItem item = (Outlook.GenericPIMItem)folderItem;
if( item.Body.ToLower().Contains( "secret sauce" ) )
{
results.Add( item.Name );
}
}
}
Body is a common property of the four PIM items I want to get at. Is there such a parent item? Seems poor API design if not? I suppose I could abstract the folder item, to make it look like there is a parent item... I also tried to do this using reflection, but couldn't quite get there.
Any suggestsion?

Looking at the documentation, I don't see a class like you want.
For Outlook 2007, the list of objects that can be in an Items collection is here. It includes things like distribution lists that don't have a body, which makes what you want unlikely.

While the PIM items might be derived from a common class, it is not creatable through the com object, but, all items also return a class property, which is an enumeration for what type of item it is. You could check this property for the four types of items you want before you cast,

Related

Reflection: Get properties/fields from individual elements of a List<>

I'm sorry in advance for the mess you're about to read, because I'm not 100% sure what I'm searching for.
I have created an entire UI system that automatically grabs a list of properties from various scripts/components on GameObjects (Unity) and creates a fitting UI input variant for them (for example, float gets a single line, Vector3 gets 3 lines, color gets something else etc.).
What goes into UI input fields creation is a Component (that we want to look into), while individual created UI inputs store this Component and Property Name. So when input changes in one of input fields, it does SetValue on Property of a Component. Now I have also created a variant where we peak into a Class of a property and basically list Property's Properties, so the UI input stores Component, Property Name, and subProperty's Name and modifies properties as such. All this works well.
So, now I hit a brick wall with Lists. I would like to treat individual elements of a list as properties so that I could pass them into my preexisting UI scheme.
tl;dr Does List<> treat it's individual elements as Properties, Fields or does it depend on the situation? How do I get these properties, fields or their respective names from this list in order to use them with my mess of an UI system? 0 work for me means treating individual elements of List as properties.
----------------------------
EDIT----------------------------
Again I am sorry for this mess of a question. It is a mixture of confused theory and description of an existing situation that I am trying to shoehorn into my already existing project (which is a bit too over the place to be easily reduced to an example).
If anyone grasped what I was asking for, the single easiest solution was to create a property which prior to listing was equated to an element of a list.
Example looks something like this:
public List<MyCustomClass> myCustomList;
[Listable("ForEdit")]
public myCustomClass myCustomPropertyForEdit
{
get;
set;
}
And before withdrawing properties of myCustomPropertyForEdit's class (myCustomClass) I would simply do:
myCustomPropertyForEdit = myCustomList[0]; //or whatever index is in question
Then later on I would do reflection on "myCustomPropertyForEdit" instead of myCustomList. I highly doubt this will ever help anyone because it touches more onto how I built methods for listing properties into my UI, but there it is just in case.
List stores references to objects, by providing an index you get a standard object reference, which you can proceed to query using reflection (do not do it against the list itself as you will get methods of the List class, and notthing related to what the list contains)
take for example:
public Class Tree
{
public int branches;
public Tree(int branch)
{
branches=branch;
}
}
List<Tree> trees = new List<Tree>();
trees.Add(new Tree(3));
now my list has one element at index 0;
so i can do trees[0].branches;
to access the fields/props of an element in trees.
list is not an array, it holds the actual item, allowing you to reference, not just the object but also its own unique variables. as long as they are public in the class.

Modifying a List of Objects through a List of Wrappers

My goal here is to retrieve a List from a class instance and then modify the objects within that list, however I do not know how the objects will be affected and need some valuable knowledge.
Let's say we have two cases:
Create a new List which gets the list from the class instance:
List<SomeType> ItemsList {get { return classInstance.ItemsList;} set {...
Create a new List of wrappers, each item in the list contains the original object with some additional properties:
List<SomeType> itemsList = classInstance.ItemsList;
List<Wrapper> wrapperList = itemsList.Select(x => new Wrapper {Item = x, IsSelected = ...
My question is, if I were to modify the objects in ItemsList and wrapperList, would the changes be reflected in the classInstance?
I will be using multiple ObservableCollections in multiple DataGrids, I have used Lists in this example simplify the situation but I'm sure the result would be the same.
Edit:
I realize the Title does not describe my problem well, I encourage anyone to help me improve it.
My question is, if I were to modify the objects in ItemsList and wrapperList, would the changes be reflected in the classInstance?
Yes, unless you create a copy SomeType and add the copy to the new collection.
The following creates a new Wrapper objects for each SomeType object...
List<Wrapper> wrapperList = itemsList.Select(x => new Wrapper {Item = x } );
...but each Wrapper object still has a reference (though the Item property) to the same SomeType object that's in classInstance.ItemsList.
When the properties of SomeType (mutable reference type) instances are changed via Wrapper then the objects in the original list change, because they are the same objects.
When the list holding Wrapper objects changes (you move, add or remove objects) the the original list is not affected.
When original list is changed (you move, add or remove objects) the list containing Wrappers is not affected.
To synchronise the collections, you should use ObservableCollection for original list and implement collection (probably also ObservableCollection-derived) for Wrappers that auto-updates itself when source collection changes.

Listbox contains does not find item, cannot remove an item

I add items to a list box like so:
foreach(myObject object in ListOfObjects)
{
mylistbox1.add(object);
}
foreach(myObject object in ListOfObjectsTwo)
{
mylistbox2.add(object);
}
Further on, I want to remove a couple of items given a specific condition. This is what I do:
foreach(myObject object in ListOfObjects3)
{
mylistbox1.items.remove(object);
mylistbox2.items.remove(object);
}
This only seems to work for mylistbox1 but not mylistbox2. When I debug, I can see that the item is there and that it has the exact same properties as the one I'm trying to remove. When I try to check if the listbox contains the item im trying to remove, it returns false.
I can't seem to make sense of it.
I c# all lists operation that are in some way required to compare objects use Equals or GetHashCode methods. In your case Equals and the default implementation wont check properties values it will only verify if the passed as argument object is in list so consider if you have the same instance in your list or just two different instances that happened to have the same properties. (the helpful VS option is make object id it will mark instance with a number)
If this is the case then you should consider overriding Equals method or find the instance that you want to delete with linq for example and pas that object to Remove method.

Inheritance and caching in ASP.NET

I've got some class hierarchy - base class which is named "Group", which contains base information about single group, and class named "RootGroup" which inherits from "Group" and extend base class with some properties. List of groups is stored in the cache using base class: e.g. IEnumerable (some of them are ordinary groups, and some of them are root groups. The point is when the collection is being retrieved from the cache and cast back to IEnumerable type, specific information of RootGrop items are lost. Is there any way to prevent this situation except of remembering type of each cached item?
Jimmy
You can check each item as you retrieve it, and cast it to its proper type:
foreach (object item in list) {
if (item is RootGroup) {
Rootgroup rootGroup = item as RootGroup;
// do stuff with rootGroup
}
}
If you are using a generic collection, like a List<Group>, you can change the foreach like this:
foreach (Group item in list)...
If I understand your question correctly, your properties of RootGroup are not being "lost". The issue is you have a Group view of a RootGroup object. In order to access RootGroup properties, you must cast the object to a RootGroup.
A simple check:
if(groupItem is RootGroup)
{
RootGroup rootGroupItem = groupItem as RootGroup;
// Do stuff
}
Another way...
//from cache
IEnumerable<Group> groupsFromCache = GetGroupsFromCache();
IEnumerable<RootGroup> rootGroups = groupsFromCache.OfType<RootGroup>();
See http://www.thinqlinq.com/default/Using-Cast-Or-OfType-Methods.aspx
This has various niceties associated with deferred execution, but without more detail I can't really tell if that makes a difference. And like other posts noted, your information associated with the child class is not lost, you just need to put it in a form where its accessible.

Unable to cast lists with Reflection in C#

I am having a lot of trouble with Reflection in C# at the moment. The app I am writing allows the user to modify the attributes of certain objects using a config file. I want to be able to save the object model (users project) to XML. The function below is called in the middle of a foreach loop, looping through a list of objects that contain all the other objects in the project within them. The idea is, that it works recursively to translate the object model into XML.
Dont worry about the call to "Unreal" that just modifes the name of the objects slightly if they contain certain words.
private void ReflectToXML(object anObject, XmlElement parentElement)
{
Type aType = anObject.GetType();
XmlElement anXmlElement = m_xml.CreateElement(Unreal(aType.Name));
parentElement.AppendChild(anXmlElement);
PropertyInfo[] pinfos = aType.GetProperties();
//loop through this objects public attributes
foreach (PropertyInfo aInfo in pinfos)
{
//if the attribute is a list
Type propertyType = aInfo.PropertyType;
if ((propertyType.IsGenericType)&&(propertyType.GetGenericTypeDefinition() == typeof(List<>)))
{
List<object> listObjects = (aInfo.GetValue(anObject,null) as List<object>);
foreach (object aListObject in listObjects)
{
ReflectToXML(aListObject, anXmlElement);
}
}
//attribute is not a list
else
anXmlElement.SetAttribute(aInfo.Name, "");
}
}
If an object attributes are just strings then it should be writing them out as string attributes in the XML. If an objects attributes are lists, then it should recursively call "ReflectToXML" passing itself in as a parameter, thereby creating the nested structure I require that nicely reflect the object model in memory.
The problem I have is with the line
List<object> listObjects = (aInfo.GetValue(anObject,null) as List<object>);
The cast doesn't work and it just returns null.
While debugging I changed the line to
object temp = aInfo.GetValue(anObject,null);
slapped a breakpoint on it to see what "GetValue" was returning. It returns a "Generic list of objects" Surely I should be able to cast that? The annoying thing is that temp becomes a generic list of objects but because i declared temp as a singular object, I can't loop through it because it has no Enumerator.
How can I loop through a list of objects when I only have it as a propertyInfo of a class?
I know at this point I will only be saving a list of empty strings out anyway, but thats fine. I would be happy to see the structure save out for now.
Thanks in advance
I'm assuming that the actual value is not a List<object> but is something like a List<string> or List<int> or some other type that isn't exactly object?
If so, then the reason that the cast is failing is because generic classes are neither co- nor contravariant.
In C# 4.0, however, you will be able to make the foreach loop work by casting to IEnumerable<object> because interfaces can be co/contravariant.
(Much) more information here: http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx
Edit:
Thinking about it, you don't need generic variance here. List<T> implements the non-generic IEnumerable. This is all you need for the foreach loop to operate, and you only need the elements as type object so just cast it to an IEnumerable instead of List<object> and everything should work fine.
Generics and reflection don't mix well, especially for lists. I would strongly suggest using (non-generic) IList, or if that fails (some generic lists don't implement it), IEnumerable (since IEnumerable<T> : IEnumerable) and invoke the Add manually.
I feel your pain, really (I maintain an OSS serialization API).
In C# 3, you can't cast Lists<T> to other types of Lists<T> even when casting to something like List<Object>. It's explicitly not allowed even when casting to List.
In 4.0 variance changes a little with interfaces with the addition of the in and out keywords.
Here is a link to Eric Lippert explaining how and why this is the case.
http://blogs.msdn.com/ericlippert/archive/tags/Covariance+and+Contravariance/default.aspx
Couldn't you just cast them to objects with OfType()?
List<object> listObjects = anObject.OfType<object>().ToList();
Update:
If the requirement wasn't for a List<object>, this would also work and involve no duplication of the list items:
var enumerableObjects = anObject.OfType<object>();

Categories