1
votes

I have a generic class that I am using Reflection to pull out the properties of the type of the generic and looking for an attribute. I am recursing into each property to do the same for each of their properties. My issue is when I come to some sort of collection property (property that is a collection) or ICollection property. I will not be able to cast the value returned from GetValue into a specific type (tried to cast into IEnumerable but does not work for generic IEnumerables).

Here is some code to help understand a little more:

 public class NotificationMessageProcessor<T> : INotificationProcessor<T>
    {
          IList<string> availableTags = new List<string>();

          public string ReplaceNotificationTags<T>(string message, T instance)
          {

             LoadTagValues(instance);
             return ReplaceTags(message);

          }

          private string ReplaceTags(string message)
          {
             foreach (KeyValuePair<string, string> tagVal in tagValues)
             {
                 message = message.Replace(string.Format("<{0}>", tagVal.Key),     tagVal.Value);
             }
             return message;
          }

          private void LoadTagValues(object val)
          {
              Type elementType = val.GetType();
              PropertyInfo[] typeProperties = elementType.GetProperties();
              foreach (PropertyInfo prop in typeProperties)
              {

                 NotificationTag[] tags =      (NotificationTag[])prop.GetCustomAttributes(typeof(NotificationTag), false);
                if (tags != null && tags.Length > 0)
                {
                    string tagName = tags[0].TagName;
                    object propValue = prop.GetValue(val, null);
                    string propTypeString = prop.PropertyType.FullName;
                    tagName = prop.ReflectedType.Name + "." + tagName;
                    if (propValue != null)
                    {
                      tagValues.Add(tagName, propValue.ToString());
                    }

                    if (propValue != null)
                    {
                       if (!prop.PropertyType.IsPrimitive)
                       {
                         LoadTagValues(propValue);
                       }
                    }
                }
                else
                {
                   if (!prop.PropertyType.IsPrimitive)
                   {
                     object propValue = null;

                        if (prop.GetGetMethod().GetParameters().Count() == 0)
                        {
                            propValue = prop.GetValue(val, null);
                        }
                        else
                        {
                           //have a collection...need to process but do not know how many in collection....
                                propValue = prop.GetValue(val, new object[] { 0 });

                        }
                    if (propValue != null)
                    {
                        LoadTagValues(propValue);
                    }
                }
            }
        }
    }




 NotificationMessageProcessor<User> userProcessor = new NotificationMessageProcessor();
    userProcessor.ReplaceNotificationTags<User>(someMessage, instanceOfUser);

The User object has the proper attributes

4
Some information on what you are actually wanting to do would be useful - all sounds a bit strange in the abstract. - Rob West

4 Answers

0
votes

From what I understand, non-generic IEnumerable will do since you don't need the type information anyway.

0
votes

You could try casting the collection type of the property to the actual type of collection?

are you doing something like the following:

List<OfObject> myCollection = new List<OfObject>;
myCollection = (List<OfObject>)objPropertyInfo.GetValue(List<ObjectHere>, Nothing);

Hope this helps

0
votes

I am doing the cast to IEnumerable, I was trying to cast the wrong object when I was having issues.

0
votes

Last Answer (Anton Gogolev) is one of the best; for example:

I had this generic function:

var fieldFetchedData = fieldQueryHandler.GetType().GetMethod("GetFilter").MakeGenericMethod(selectedParameter.ParameterType).Invoke(fieldQueryHandler,fieldParameters.ToArray());

which itself also returned a generic list (List<[Unknown Model Type]>...)

I looked everywhere to get a single result from it, but I had to cast it any way before doing that, and there was no way to define user or any other model class (which I don't know which one it should be) even through generics. Once I saw it, I said to myself, I tried many ways, let also give this a try, and so I did it like this:

IEnumerator enumeratorFetchedData = ((IEnumerable) fieldFetchedData).GetEnumerator();
object obj = enumeratorFetchedData.MoveNext()? enumeratorFetchedData.Current:null;

and it worked as it should!!