2013-12-04 3 views
0

У меня есть следующий сценарий:Определить члена класса от типа

1) Класс:

public class C 
{ 
    public List<MyType> ListOfMyTypeObjects; 
    public List<MyOtherType> ListOfMyOtherTypeObjects; 
    public C() 
    { 
     this.ListOfMyTypeObjects = new List<MyType>; 
     this.ListOfMyOtherTypeObjects = new List<MyOtherType>; 
    } 
} 

2) Интерфейс:

public interface IInterface<T> 
{ 
    object CreateObject(T source); 
} 

3) Реализация класса:

public class Implementing<T> : IInterface<T> where T: SomeGeneralType 
{ 
    public object CreateObject(T source, int key) 
    { 
     //i know T can be of type MyType, but it can also be MyOtherType 
     C c = (C)storage[key]; 
     //here, i would like to add to one of my members the source object, 
     //but without specifically know it is called that; in other words, i would like 
     //to scan c and find if it has any List<T> members; in that case, add to the 
     //found member (which is unique) the source object and return something, 
     //doesn't matter what 
    } 
} 

4) Объект экземпляра:

IDicionary<int, C> storage = new Dictionary{{1, new C()}}; 

Как я могу определить элемент, который соответствует желаемому типу, и как я могу добавить к нему объект?

+0

Чтобы получить тип из общего «Т», вы можете использовать «typeof»: Type givenType = typeof (T); –

ответ

1

На самом деле я бы не использовал отражение для этого, так как у вас есть фиксированное количество списков в классе C, вы можете добавить метод, который возвращает соответствующий список:

public class C 
{ 
    public List<MyType> ListOfMyTypeObjects; 
    public List<MyOtherType> ListOfMyOtherTypeObjects; 
    public C() 
    { 
     this.ListOfMyTypeObjects = new List<MyType>; 
     this.ListOfMyOtherTypeObjects = new List<MyOtherType>; 
    } 

    public List<T> GetListFor<T>() 
    { 
     if(typeof(T) == typeof(MyType)) 
      return ListOfMyTypeObjects as List<T>; 
     else if(typeof(T) == typeof(MyOtherType)) 
      return ListOfMyOtherTypeObjects as List<T>; 
     else 
      throw new TypeArgumentException("No list properties defined for " + 
       typeof(T).Name); 
    } 
} 

Тогда вы можете сделать это:

public object CreateObject(T source, int key) 
{ 
    C c = (C)storage[key]; 
    var list = c.GetListFor<T>(); 
    list.Add(source); 

    return source; 
} 
+0

Да, я тоже постараюсь избежать отражения, но, к сожалению, нет никаких указаний на добавление новых списков в C, поэтому я не хочу изменять определение C.GetListFor . Но спасибо. –

+0

Вы изменяете метод _when_ вы добавляете новый список - есть в пределах того же класса :) –

+0

Ну, вы владели мной! Я выберу эту реализацию, потому что она избегает размышлений. Также был поддержан следующий ответ, потому что он выглядит элегантно. Благодарю. –

0

вы можете использовать отражение что-то вроде этого

using System.Reflection; 
    PropertyInfo[] properties = Item.GetType().GetProperties(); 
    you can iterate through propeerties 

     foreach (PropertyInfo p in properties) 
       {   
    if (p.PropertyType.IsGenericType && p.PropertyType.GetGenericTypeDefinition() == typeof(Dictionary<,>)) 
1

Вы можете использовать отражение (поиск для общего поля списка):

void Main() 
{ 
    var c = new C(); 
    Set(new MyType(), c); 
    Set(new MyOtherType(), c); 
} 

void Set<T>(T item, C c) 
{ 
    var field = typeof(C).GetFields().SingleOrDefault(x => x.FieldType.GetInterface(typeof(IList).FullName) != null && 
                  x.FieldType.GetGenericArguments().All(ft => ft == typeof(T))); 
    ((IList)field.GetValue(c)).Add(item); 
} 

или вы можете использовать dynamic:

void Main() 
{ 
    var c = new C(); 
    SetDynamic(new MyType(), c); 
    SetDynamic(new MyOtherType(), c); 
} 

void SetDynamic<T>(T item, C c) 
{ 
    ((dynamic)c).Add(item); 
} 

public class C 
{ 
    ///... 

    public void Add(MyType item) 
    { 
     ListOfMyTypeObjects.Add(item); 
    } 

    public void Add(MyOtherType item) 
    { 
     ListOfMyOtherTypeObjects.Add(item); 
    } 
} 
0

Я считаю, что была хорошая причина для серьезного различия между FieldInfo и PropertyInfo, несмотря на их субъекты намеренно разделяют так много концептуальных сходств. В настоящее время я не могу придумать ничего хорошего.

static IEnumerable<MemberInfo> GetMembers(Type type) 
{ 
    var properties = type.GetProperties(); 
    var fields = type.GetFields(); 
    return properties.Cast<MemberInfo>().Concat(fields); 
} 
static Type GetMemberType(MemberInfo m) 
{ 
    return m is PropertyInfo 
    ? (m as PropertyInfo).PropertyType 
    : (m as FieldInfo).FieldType; 
} 
Смежные вопросы